[svn] / trunk / xvidcore / src / motion / motion_est.c Repository:
ViewVC logotype

Diff of /trunk/xvidcore/src/motion/motion_est.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 181, Wed May 22 12:42:25 2002 UTC revision 476, Thu Sep 12 18:53:11 2002 UTC
# Line 1  Line 1 
1  /**************************************************************************  /*****************************************************************************
2   *   *
3   *  Modifications:   *  XVID MPEG-4 VIDEO CODEC
4     *  - Motion Estimation module -
5   *   *
6   *      01.05.2002      updated MotionEstimationBVOP   *  Copyright(C) 2002 Christoph Lampert <gruel@web.de>
7   *      25.04.2002 partial prevMB conversion   *  Copyright(C) 2002 Michael Militzer <michael@xvid.org>
8   *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>   *  Copyright(C) 2002 Edouard Gomez <ed.gomez@wanadoo.fr>
  *  14.04.2002 added MotionEstimationBVOP()  
  *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between  
  *             EPZS and EPZS^2  
  *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop  
  *             PMVFast_Refine to support multiple searches with different start points  
  *  07.01.2002 uv-block-based interpolation  
  *  06.01.2002 INTER/INTRA-decision is now done before any SEARCH8 (speedup)  
  *             changed INTER_BIAS to 150 (as suggested by suxen_drol)  
  *             removed halfpel refinement step in PMVfastSearch8 + quality=5  
  *             added new quality mode = 6 which performs halfpel refinement  
  *             filesize difference between quality 5 and 6 is smaller than 1%  
  *             (Isibaar)  
  *  31.12.2001 PMVfastSearch16 and PMVfastSearch8 (gruel)  
  *  30.12.2001 get_range/MotionSearchX simplified; blue/green bug fix  
  *  22.12.2001 commented best_point==99 check  
  *  19.12.2001 modified get_range (purple bug fix)  
  *  15.12.2001 moved pmv displacement from mbprediction  
  *  02.12.2001 motion estimation/compensation split (Isibaar)  
  *  16.11.2001 rewrote/tweaked search algorithms; pross@cs.rmit.edu.au  
  *  10.11.2001 support for sad16/sad8 functions  
  *  28.08.2001 reactivated MODE_INTER4V for EXT_MODE  
  *  24.08.2001 removed MODE_INTER4V_Q, disabled MODE_INTER4V for EXT_MODE  
  *  22.08.2001 added MODE_INTER4V_Q  
  *  20.08.2001 added pragma to get rid of internal compiler error with VC6  
  *             idea by Cyril. Thanks.  
9   *   *
10   *  Michael Militzer <isibaar@videocoding.de>   *  This program is an implementation of a part of one or more MPEG-4
11     *  Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
12     *  to use this software module in hardware or software products are
13     *  advised that its use may infringe existing patents or copyrights, and
14     *  any such use would be at such party's own risk.  The original
15     *  developer of this software module and his/her company, and subsequent
16     *  editors and their companies, will have no liability for use of this
17     *  software or modifications or derivatives thereof.
18   *   *
19   **************************************************************************/   *  This program is free software; you can redistribute it and/or modify
20     *  it under the terms of the GNU General Public License as published by
21     *  the Free Software Foundation; either version 2 of the License, or
22     *  (at your option) any later version.
23     *
24     *  This program is distributed in the hope that it will be useful,
25     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
26     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27     *  GNU General Public License for more details.
28     *
29     *  You should have received a copy of the GNU General Public License
30     *  along with this program; if not, write to the Free Software
31     *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
32     *
33     *************************************************************************/
34    
35  #include <assert.h>  #include <assert.h>
36  #include <stdio.h>  #include <stdio.h>
# Line 47  Line 44 
44  #include "motion.h"  #include "motion.h"
45  #include "sad.h"  #include "sad.h"
46    
 // very large value  
 #define MV_MAX_ERROR    (4096 * 256)  
   
 // stop search if sdelta < THRESHOLD  
 #define MV16_THRESHOLD  192  
 #define MV8_THRESHOLD   56  
   
 #define NEIGH_MOVE_THRESH 0  
 // how much a block's MV must differ from his neighbour  
 // to be search for INTER4V. The more, the faster...  
   
 /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  
 /* nb  = vop pixels * 2^(bpp-8) */  
 #define MV16_00_BIAS    (128+1)  
 #define MV8_00_BIAS     (0)  
   
 /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */  
 #define MV16_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 MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
 int32_t PMVfastSearch16(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
 int32_t EPZSSearch16(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
47    
 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, const int start_y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
 int32_t EPZSSearch8(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const int start_x, const int start_y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
   
 typedef int32_t (MainSearch16Func)(  
         const uint8_t * const pRef,  
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const uint8_t * const cur,  
         const int x, const int y,  
         int32_t startx, int32_t starty,  
         int32_t iMinSAD,  
         VECTOR * const currMV,  
         const VECTOR * const pmv,  
         const int32_t min_dx, const int32_t max_dx,  
         const int32_t min_dy, const int32_t max_dy,  
         const int32_t iEdgedWidth,  
         const int32_t iDiamondSize,  
         const int32_t iFcode,  
         const int32_t iQuant,  
         int iFound);  
   
 typedef MainSearch16Func* MainSearch16FuncPtr;  
   
   
 typedef int32_t (MainSearch8Func)(  
         const uint8_t * const pRef,  
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const uint8_t * const cur,  
         const int x, const int y,  
         int32_t startx, int32_t starty,  
         int32_t iMinSAD,  
         VECTOR * const currMV,  
         const VECTOR * const pmv,  
         const int32_t min_dx, const int32_t max_dx,  
         const int32_t min_dy, const int32_t max_dy,  
         const int32_t iEdgedWidth,  
         const int32_t iDiamondSize,  
         const int32_t iFcode,  
         const int32_t iQuant,  
         int iFound);  
   
 typedef MainSearch8Func* MainSearch8FuncPtr;  
48    
49  static int32_t lambda_vec16[32] =  /* rounded values for lambda param for weight of motion bits as in modified H.26L */  static int32_t lambda_vec16[32] =  /* rounded values for lambda param for weight of motion bits as in modified H.26L */
50          {     0    ,(int)(1.00235+0.5), (int)(1.15582+0.5), (int)(1.31976+0.5), (int)(1.49591+0.5), (int)(1.68601+0.5),  { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),
51          (int)(1.89187+0.5), (int)(2.11542+0.5), (int)(2.35878+0.5), (int)(2.62429+0.5), (int)(2.91455+0.5),                  (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),
52          (int)(3.23253+0.5), (int)(3.58158+0.5), (int)(3.96555+0.5), (int)(4.38887+0.5), (int)(4.85673+0.5),          (int) (1.89187 + 0.5), (int) (2.11542 + 0.5), (int) (2.35878 + 0.5),
53          (int)(5.37519+0.5), (int)(5.95144+0.5), (int)(6.59408+0.5), (int)(7.31349+0.5), (int)(8.12242+0.5),                  (int) (2.62429 + 0.5), (int) (2.91455 + 0.5),
54          (int)(9.03669+0.5), (int)(10.0763+0.5), (int)(11.2669+0.5), (int)(12.6426+0.5), (int)(14.2493+0.5),          (int) (3.23253 + 0.5), (int) (3.58158 + 0.5), (int) (3.96555 + 0.5),
55          (int)(16.1512+0.5), (int)(18.442+0.5),  (int)(21.2656+0.5), (int)(24.8580+0.5), (int)(29.6436+0.5),                  (int) (4.38887 + 0.5), (int) (4.85673 + 0.5),
56          (int)(36.4949+0.5)      };          (int) (5.37519 + 0.5), (int) (5.95144 + 0.5), (int) (6.59408 + 0.5),
57                    (int) (7.31349 + 0.5), (int) (8.12242 + 0.5),
58            (int) (9.03669 + 0.5), (int) (10.0763 + 0.5), (int) (11.2669 + 0.5),
59                    (int) (12.6426 + 0.5), (int) (14.2493 + 0.5),
60            (int) (16.1512 + 0.5), (int) (18.442 + 0.5), (int) (21.2656 + 0.5),
61                    (int) (24.8580 + 0.5), (int) (29.6436 + 0.5),
62            (int) (36.4949 + 0.5)
63    };
64    
65  static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now*/  static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now*/
66    
# Line 212  Line 75 
75  };  };
76    
77    
78  static __inline uint32_t mv_bits(int32_t component, const uint32_t iFcode)  static __inline uint32_t
79    mv_bits(int32_t component,
80                    const uint32_t iFcode)
81  {  {
82      if (component == 0)      if (component == 0)
83                  return 1;                  return 1;
# Line 220  Line 85 
85      if (component < 0)      if (component < 0)
86                  component = -component;                  component = -component;
87    
88      if (iFcode == 1)          if (iFcode == 1) {
     {  
89                  if (component > 32)                  if (component > 32)
90                      component = 32;                      component = 32;
91    
# Line 238  Line 102 
102  }  }
103    
104    
105  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)  static __inline uint32_t
106    calc_delta_16(const int32_t dx,
107                              const int32_t dy,
108                              const uint32_t iFcode,
109                              const uint32_t iQuant)
110  {  {
111          return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));          return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) +
112                                                                                                              mv_bits(dy, iFcode));
113  }  }
114    
115  static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)  static __inline uint32_t
116    calc_delta_8(const int32_t dx,
117                             const int32_t dy,
118                             const uint32_t iFcode,
119                             const uint32_t iQuant)
120  {  {
121      return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));          return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) +
122                                                                                                       mv_bits(dy, iFcode));
123  }  }
124    
125    bool
126    MotionEstimation(MBParam * const pParam,
   
   
 #ifndef SEARCH16  
 #define SEARCH16        PMVfastSearch16  
 //#define SEARCH16      FullSearch16  
 //#define SEARCH16      EPZSSearch16  
 #endif  
   
 #ifndef SEARCH8  
 #define SEARCH8         PMVfastSearch8  
 //#define SEARCH8       EPZSSearch8  
 #endif  
   
 bool MotionEstimation(  
         MBParam * const pParam,  
127          FRAMEINFO * const current,          FRAMEINFO * const current,
128          FRAMEINFO * const reference,          FRAMEINFO * const reference,
129          const IMAGE * const pRefH,          const IMAGE * const pRefH,
130          const IMAGE * const pRefV,          const IMAGE * const pRefV,
131          const IMAGE * const pRefHV,          const IMAGE * const pRefHV,
132          const uint32_t iLimit)          const uint32_t iLimit)
   
133  {  {
134          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
135          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
136          MACROBLOCK * const pMBs = current->mbs;          MACROBLOCK * const pMBs = current->mbs;
137          MACROBLOCK * const prevMBs = reference->mbs;    // previous frame          MACROBLOCK *const prevMBs = reference->mbs;
   
138          const IMAGE * const pCurrent = &current->image;          const IMAGE * const pCurrent = &current->image;
139          const IMAGE * const pRef = &reference->image;          const IMAGE * const pRef = &reference->image;
140    
141          const VECTOR zeroMV = {0,0};          static const VECTOR zeroMV = { 0, 0 };
142            VECTOR predMV;
143    
144          int32_t x, y;          uint32_t x, y;
145          int32_t iIntra = 0;          uint32_t iIntra = 0;
146          VECTOR pmv;          VECTOR pmv;
147    
148          if (sadInit)          if (sadInit)
149                  (*sadInit)();                  (*sadInit)();
150    
151          for (y = 0; y < iHcount; y++)          for (y = 0; y < iHcount; y++)   {
152                  for (x = 0; x < iWcount; x++)                  for (x = 0; x < iWcount; x ++)  {
153                  {  
154                          MACROBLOCK* const pMB = &pMBs[x + y * iWcount];                          MACROBLOCK* const pMB = &pMBs[x + y * iWcount];
155    
156                          pMB->sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          if (pMB->mode == MODE_NOT_CODED)
157                                           x, y, current->motion_flags, current->quant, current->fcode,                                  continue;
                                          pParam, pMBs, prevMBs, &pMB->mv16, &pMB->pmvs[0]);  
158    
159                            predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
160    
161                          if (0 < (pMB->sad16 - MV16_INTER_BIAS))                          pMB->sad16 =
162                          {                                  SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
163                                                     x, y, predMV.x, predMV.y, predMV.x, predMV.y,
164                                                     current->motion_flags, current->quant,
165                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
166                                                     &pMB->pmvs[0]);
167    
168                            if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
169                                  int32_t deviation;                                  int32_t deviation;
170                                  deviation = dev16(pCurrent->y + x*16 + y*16*pParam->edged_width,  
171                                    deviation =
172                                            dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
173                                                           pParam->edged_width);                                                           pParam->edged_width);
174    
175                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS))                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
                                 {  
176                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
177                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
178                                                                   = pMB->mvs[2] = pMB->mvs[3] = zeroMV;                                                  pMB->mvs[3] = zeroMV;
179                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1]                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
180                                                               = pMB->sad8[2] = pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
181    
182                                          iIntra++;                                          iIntra++;
183                                          if (iIntra >= iLimit)                                          if (iIntra >= iLimit)
# Line 322  Line 186 
186                                          continue;                                          continue;
187                                  }                                  }
188                          }                          }
                         pMB->mode = MODE_INTER;  
                         pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;  
            pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = pMB->sad16;  
                 }  
   
         // we try to do as few INTER4V-searches as possible. So we split ME in two parts, normal  
         // SEARCH16 and only for special blocks SEARCH8. May this should be modified for quality  
         // levels.  
   
   
189    
190                            pmv = pMB->pmvs[0];
191          if (current->global_flags & XVID_INTER4V)          if (current->global_flags & XVID_INTER4V)
192                  for (y = 0; y < iHcount; y++)                                  if ((!(current->global_flags & XVID_LUMIMASKING) ||
193                          for (x = 0; x < iWcount; x++)                                           pMB->dquant == NO_CHANGE)) {
                         {  
                                 MACROBLOCK* const pMB = &pMBs[x + y * iWcount];  
   
                                 if (pMB->mode == MODE_INTRA)  
                                         continue;  
   
   
                                 if ( (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE) )  
                                 {  
                                 int32_t neigh=0;  
   
                                 if (x>0)  
                                 {       neigh += abs((pMB->mv16.x)-((pMB-1)->mv16.x));  
                                         neigh += abs((pMB->mv16.y)-((pMB-1)->mv16.y));  
                                 }  
                                 if (y>0)  
                                 {       neigh += abs((pMB->mv16.x)-((pMB-iWcount)->mv16.x));  
                                         neigh += abs((pMB->mv16.y)-((pMB-iWcount)->mv16.y));  
                                 }  
                                 if (x<(iWcount-1))  
                                 {       neigh += abs((pMB->mv16.x)-((pMB+1)->mv16.x));  
                                         neigh += abs((pMB->mv16.y)-((pMB+1)->mv16.y));  
                                 }  
                                 if (y<(iHcount-1))  
                                 {       neigh += abs((pMB->mv16.x)-((pMB+iHcount)->mv16.x));  
                                         neigh += abs((pMB->mv16.y)-((pMB+iHcount)->mv16.y));  
                                 }  
   
                                 if (neigh > NEIGH_MOVE_THRESH)  
                                 {  
194                                          int32_t sad8 = IMV16X16 * current->quant;                                          int32_t sad8 = IMV16X16 * current->quant;
195    
196                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16) {
197                                          sad8 += pMB->sad8[0]                                                  sad8 += pMB->sad8[0] =
198                                                  = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
199                                                                 2*x, 2*y, pMB->mv16.x, pMB->mv16.y,                                                                          pCurrent, 2 * x, 2 * y,
200                                                                     current->motion_flags, current->quant, current->fcode,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
201                                                                 pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);                                                                          current->motion_flags,
202                                                                            current->quant, current->fcode, pParam,
203                                          if (sad8 < pMB->sad16)                                                                          pMBs, prevMBs, &pMB->mvs[0],
204                                          sad8 += pMB->sad8[1]                                                                          &pMB->pmvs[0]);
205                                                  = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                          }
206                                         2*x+1, 2*y, pMB->mv16.x, pMB->mv16.y,                                          if (sad8 < pMB->sad16) {
207                                                          current->motion_flags, current->quant, current->fcode,  
208                                                          pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);                                                  predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
209                                                    sad8 += pMB->sad8[1] =
210                                          if (sad8 < pMB->sad16)                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
211                                          sad8 += pMB->sad8[2]                                                                          pCurrent, 2 * x + 1, 2 * y,
212                                                  = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
213                                                          2*x, 2*y+1, pMB->mv16.x, pMB->mv16.y,                                                                          current->motion_flags,
214                                                          current->motion_flags, current->quant, current->fcode,                                                                          current->quant, current->fcode, pParam,
215                                                          pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);                                                                          pMBs, prevMBs, &pMB->mvs[1],
216                                                                            &pMB->pmvs[1]);
217                                          if (sad8 < pMB->sad16)                                          }
218                                          sad8 += pMB->sad8[3]                                          if (sad8 < pMB->sad16) {
219                                                  = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                  predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
220                                                          2*x+1, 2*y+1, pMB->mv16.x, pMB->mv16.y,                                                  sad8 += pMB->sad8[2] =
221                                                          current->motion_flags, current->quant, current->fcode,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
222                                                          pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);                                                                          pCurrent, 2 * x, 2 * y + 1,
223                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
224                                                                            current->motion_flags,
225                                                                            current->quant, current->fcode, pParam,
226                                                                            pMBs, prevMBs, &pMB->mvs[2],
227                                                                            &pMB->pmvs[2]);
228                                            }
229                                            if (sad8 < pMB->sad16) {
230                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
231                                                    sad8 += pMB->sad8[3] =
232                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
233                                                                            pCurrent, 2 * x + 1, 2 * y + 1,
234                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
235                                                                            current->motion_flags,
236                                                                            current->quant, current->fcode, pParam,
237                                                                            pMBs, prevMBs,
238                                                                            &pMB->mvs[3],
239                                                                            &pMB->pmvs[3]);
240                                            }
241    
242                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
243                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
244                          */                          */
245    
246                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16) {
                                         {  
247                                                  pMB->mode = MODE_INTER4V;                                                  pMB->mode = MODE_INTER4V;
248                        pMB->sad8[0] *= 4;                        pMB->sad8[0] *= 4;
249                                                  pMB->sad8[1] *= 4;                                                  pMB->sad8[1] *= 4;
# Line 410  Line 252 
252                                                  continue;                                                  continue;
253                                          }                                          }
254    
                                         pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;  
255                                  }                                  }
256    
257                            pMB->mode = MODE_INTER;
258                            pMB->pmvs[0] = pmv;     /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
259                            pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
260                            pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
261                                    pMB->sad16;
262                                  }                                  }
   
                 // get_pmv has to be called again, because inter4v changes predictors  
   
                         pmv = get_pmv(pMBs, x, y, pParam->mb_width, 0);  
                         pMB->pmvs[0].x = pMB->mv16.x - pmv.x;   /* the other pmvs are only needed in INTER4V-mode */  
                         pMB->pmvs[0].y = pMB->mv16.y - pmv.y;  
   
263                          }                          }
264    
265          return 0;          return 0;
266  }  }
267    
268    
269  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
270    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
271      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
272    { \    { \
273      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); \
274      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);\
275      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
276      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
277  }  }
278    
279  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
280      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); \
281      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);\
282      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
283      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
284  }  }
# Line 448  Line 288 
288      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
289    { \    { \
290      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); \
291      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);\
292      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
293      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
294  }  }
# Line 458  Line 298 
298      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
299    { \    { \
300      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
301      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
302      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
303      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
304  }  }
# Line 468  Line 308 
308      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
309    { \    { \
310      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
311      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
312      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
313      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
314  }  }
# Line 476  Line 316 
316    
317  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
318    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); \
319    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);\
320    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
321    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
322  }  }
# Line 484  Line 324 
324  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
325    { \    { \
326      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); \
327      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);\
328      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
329      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
330  }  }
# Line 494  Line 334 
334      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
335    { \    { \
336      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); \
337      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);\
338      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
339      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
340  }  }
# Line 504  Line 344 
344      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
345    { \    { \
346      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
347      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
348      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
349      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
350  }  }
# Line 514  Line 354 
354      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
355    { \    { \
356      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
357      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
358      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
359      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
360  }  }
# Line 540  Line 380 
380          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
381          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
382          int32_t iSAD;          int32_t iSAD;
383          int32_t pred_x,pred_y;          VECTOR pred;
384    
385          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);  
386            pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
387    
388          iSAD = sad16( cur,          iSAD = sad16( cur,
389                  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 552  Line 393 
393    
394          currMV->x = 0;          currMV->x = 0;
395          currMV->y = 0;          currMV->y = 0;
396          currPMV->x = -pred_x;          currPMV->x = -pred.x;
397          currPMV->y = -pred_y;          currPMV->y = -pred.y;
398    
399          return iSAD;          return iSAD;
400    
401  }  }
402  */  */
403    
404  int32_t Diamond16_MainSearch(  int32_t
405          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
406          const uint8_t * const pRefH,          const uint8_t * const pRefH,
407          const uint8_t * const pRefV,          const uint8_t * const pRefV,
408          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
409          const uint8_t * const cur,          const uint8_t * const cur,
410          const int x, const int y,                                           const int x,
411          int32_t startx, int32_t starty,                                           const int y,
412          int32_t iMinSAD,                                           const int start_x,
413                                             const int start_y,
414                                             int iMinSAD,
415          VECTOR * const currMV,          VECTOR * const currMV,
416          const VECTOR * const pmv,                                           const int center_x,
417          const int32_t min_dx, const int32_t max_dx,                                           const int center_y,
418          const int32_t min_dy, const int32_t max_dy,                                           const int32_t min_dx,
419                                             const int32_t max_dx,
420                                             const int32_t min_dy,
421                                             const int32_t max_dy,
422          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
423          const int32_t iDiamondSize,          const int32_t iDiamondSize,
424          const int32_t iFcode,          const int32_t iFcode,
# Line 582  Line 428 
428  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
429    
430          int32_t iDirection=0;          int32_t iDirection=0;
431            int32_t iDirectionBackup;
432          int32_t iSAD;          int32_t iSAD;
433          VECTOR backupMV;          VECTOR backupMV;
434          backupMV.x = startx;  
435          backupMV.y = starty;          backupMV.x = start_x;
436            backupMV.y = start_y;
437    
438  /* 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 */
439    
# Line 594  Line 442 
442          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
443          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
444    
445          if (iDirection)          if (iDirection) {
446                  while (!iFound)                  while (!iFound) {
                 {  
447                          iFound = 1;                          iFound = 1;
448                          backupMV=*currMV;                          backupMV=*currMV;
449                            iDirectionBackup = iDirection;
450    
451                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
452                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
453                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
454                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
455                          if ( iDirection != 4)                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
456                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                     backupMV.y, 2);
457                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
458                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
459                  }                                                                                     backupMV.y - iDiamondSize, 3);
460          else                          if (iDirectionBackup != 3)
461          {                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
462                  currMV->x = startx;                                                                                     backupMV.y + iDiamondSize, 4);
463                  currMV->y = starty;                  }
464            } else {
465                    currMV->x = start_x;
466                    currMV->y = start_y;
467          }          }
468          return iMinSAD;          return iMinSAD;
469  }  }
470    
471  int32_t Square16_MainSearch(  int32_t
472                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
473                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
474                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
475                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
476                                          const uint8_t * const cur,                                          const uint8_t * const cur,
477                                          const int x, const int y,                                          const int x,
478                                          int32_t startx, int32_t starty,                                          const int y,
479                                          int32_t iMinSAD,                                          const int start_x,
480                                            const int start_y,
481                                            int iMinSAD,
482                                          VECTOR * const currMV,                                          VECTOR * const currMV,
483                                          const VECTOR * const pmv,                                          const int center_x,
484                                          const int32_t min_dx, const int32_t max_dx,                                          const int center_y,
485                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
486                                            const int32_t max_dx,
487                                            const int32_t min_dy,
488                                            const int32_t max_dy,
489                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
490                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
491                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 641  Line 497 
497          int32_t iDirection=0;          int32_t iDirection=0;
498          int32_t iSAD;          int32_t iSAD;
499          VECTOR backupMV;          VECTOR backupMV;
500          backupMV.x = startx;  
501          backupMV.y = starty;          backupMV.x = start_x;
502            backupMV.y = start_y;
503    
504  /* It's one search with full square pattern, and new parts for all following diamonds */  /* It's one search with full square pattern, and new parts for all following diamonds */
505    
# Line 657  Line 514 
514          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
515          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
516    
517          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
518          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
519          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
520          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
521            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
522                                                             backupMV.y - iDiamondSize, 7);
523            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
524                                                             backupMV.y + iDiamondSize, 8);
525    
526    
527          if (iDirection)          if (iDirection) {
528                  while (!iFound)                  while (!iFound) {
                 {  
529                          iFound = 1;                          iFound = 1;
530                          backupMV=*currMV;                          backupMV=*currMV;
531    
532                          switch (iDirection)                          switch (iDirection) {
                         {  
533                                  case 1:                                  case 1:
534                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
535                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
536                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
537                                                                                     backupMV.y - iDiamondSize, 5);
538                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
539                                                                                     backupMV.y - iDiamondSize, 7);
540                                          break;                                          break;
541                                  case 2:                                  case 2:
542                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
543                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
544                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
545                                                                                     backupMV.y + iDiamondSize, 6);
546                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
547                                                                                     backupMV.y + iDiamondSize, 8);
548                                          break;                                          break;
549    
550                                  case 3:                                  case 3:
551                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
552                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
553                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
554                                                                                     backupMV.y - iDiamondSize, 7);
555                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
556                                                                                     backupMV.y + iDiamondSize, 8);
557                                          break;                                          break;
558    
559                                  case 4:                                  case 4:
560                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
561                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
562                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
563                                                                                     backupMV.y - iDiamondSize, 5);
564                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
565                                                                                     backupMV.y + iDiamondSize, 6);
566                                          break;                                          break;
567    
568                                  case 5:                                  case 5:
569                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
570                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
571                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
572                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
573                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
574                                                                                     backupMV.y - iDiamondSize, 5);
575                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
576                                                                                     backupMV.y + iDiamondSize, 6);
577                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
578                                                                                     backupMV.y - iDiamondSize, 7);
579                                          break;                                          break;
580    
581                                  case 6:                                  case 6:
582                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
583                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
584                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
585                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
586                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
587                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
588                                                                                     backupMV.y - iDiamondSize, 5);
589                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
590                                                                                     backupMV.y + iDiamondSize, 6);
591                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
592                                                                                     backupMV.y + iDiamondSize, 8);
593    
594                                          break;                                          break;
595    
596                                  case 7:                                  case 7:
597                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
598                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
599                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
600                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
601                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
602                                                                                     backupMV.y - iDiamondSize, 5);
603                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
604                                                                                     backupMV.y - iDiamondSize, 7);
605                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
606                                                                                     backupMV.y + iDiamondSize, 8);
607                                          break;                                          break;
608    
609                                  case 8:                                  case 8:
610                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
611                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
612                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
613                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
614                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
615                                                                                     backupMV.y + iDiamondSize, 6);
616                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
617                                                                                     backupMV.y - iDiamondSize, 7);
618                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
619                                                                                     backupMV.y + iDiamondSize, 8);
620                                          break;                                          break;
621                          default:                          default:
622                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
623                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
624                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
625                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
626                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
627                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
628                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
629                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
630                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
631                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
632                                                                                     backupMV.y - iDiamondSize, 5);
633                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
634                                                                                     backupMV.y + iDiamondSize, 6);
635                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
636                                                                                     backupMV.y - iDiamondSize, 7);
637                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
638                                                                                     backupMV.y + iDiamondSize, 8);
639                                          break;                                          break;
640                          }                          }
641                  }                  }
642          else          } else {
643                  {                  currMV->x = start_x;
644                          currMV->x = startx;                  currMV->y = start_y;
                         currMV->y = starty;  
645                  }                  }
646          return iMinSAD;          return iMinSAD;
647  }  }
648    
649    
650  int32_t Full16_MainSearch(  int32_t
651                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
652                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
653                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
654                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
655                                          const uint8_t * const cur,                                          const uint8_t * const cur,
656                                          const int x, const int y,                                    const int x,
657                                          int32_t startx, int32_t starty,                                    const int y,
658                                          int32_t iMinSAD,                                    const int start_x,
659                                      const int start_y,
660                                      int iMinSAD,
661                                          VECTOR * const currMV,                                          VECTOR * const currMV,
662                                          const VECTOR * const pmv,                                    const int center_x,
663                                          const int32_t min_dx, const int32_t max_dx,                                    const int center_y,
664                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
665                                      const int32_t max_dx,
666                                      const int32_t min_dy,
667                                      const int32_t max_dy,
668                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
669                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
670                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 771  Line 674 
674          int32_t iSAD;          int32_t iSAD;
675          int32_t dx,dy;          int32_t dx,dy;
676          VECTOR backupMV;          VECTOR backupMV;
677          backupMV.x = startx;  
678          backupMV.y = starty;          backupMV.x = start_x;
679            backupMV.y = start_y;
680    
681          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
682                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 781  Line 685 
685          return iMinSAD;          return iMinSAD;
686  }  }
687    
688  int32_t AdvDiamond16_MainSearch(  int32_t
689          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
690          const uint8_t * const pRefH,          const uint8_t * const pRefH,
691          const uint8_t * const pRefV,          const uint8_t * const pRefV,
692          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
693          const uint8_t * const cur,          const uint8_t * const cur,
694          const int x, const int y,                                                  const int x,
695          int32_t startx, int32_t starty,                                                  const int y,
696          int32_t iMinSAD,                                                  const int start_xi,
697                                                    const int start_yi,
698                                                    int iMinSAD,
699          VECTOR * const currMV,          VECTOR * const currMV,
700          const VECTOR * const pmv,                                                  const int center_x,
701          const int32_t min_dx, const int32_t max_dx,                                                  const int center_y,
702          const int32_t min_dy, const int32_t max_dy,                                                  const int32_t min_dx,
703                                                    const int32_t max_dx,
704                                                    const int32_t min_dy,
705                                                    const int32_t max_dy,
706          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
707          const int32_t iDiamondSize,          const int32_t iDiamondSize,
708          const int32_t iFcode,          const int32_t iFcode,
# Line 802  Line 711 
711  {  {
712    
713          int32_t iSAD;          int32_t iSAD;
714            int start_x = start_xi, start_y = start_yi;
715    
716  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
717    
718          if (iDirection)          if (iDirection) {
719          {                  CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
720                  CHECK_MV16_CANDIDATE(startx-iDiamondSize, starty);                  CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
721                  CHECK_MV16_CANDIDATE(startx+iDiamondSize, starty);                  CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
722                  CHECK_MV16_CANDIDATE(startx, starty-iDiamondSize);                  CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
723                  CHECK_MV16_CANDIDATE(startx, starty+iDiamondSize);          } else {
         }  
         else  
         {  
724                  int bDirection = 1+2+4+8;                  int bDirection = 1+2+4+8;
725                  do  
726                  {                  do {
727                          iDirection = 0;                          iDirection = 0;
728                          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)                          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)
729                                  CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize,starty,1);                                  CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
730    
731                          if (bDirection&2)                          if (bDirection&2)
732                                  CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize,starty,2);                                  CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
733    
734                          if (bDirection&4)                          if (bDirection&4)
735                                  CHECK_MV16_CANDIDATE_DIR(startx,starty-iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
736    
737                          if (bDirection&8)                          if (bDirection&8)
738                                  CHECK_MV16_CANDIDATE_DIR(startx,starty+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
739    
740                          /* now we're doing diagonal checks near our candidate */                          /* now we're doing diagonal checks near our candidate */
741    
# Line 836  Line 743 
743                          {                          {
744                                  bDirection = iDirection;                                  bDirection = iDirection;
745                                  iDirection = 0;                                  iDirection = 0;
746                                  startx=currMV->x; starty=currMV->y;                                  start_x = currMV->x;
747                                    start_y = currMV->y;
748                                  if (bDirection & 3) //our candidate is left or right                                  if (bDirection & 3) //our candidate is left or right
749                                  {                                  {
750                                          CHECK_MV16_CANDIDATE_DIR(startx,starty+iDiamondSize, 8);                                          CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
751                                          CHECK_MV16_CANDIDATE_DIR(startx,starty-iDiamondSize, 4);                                          CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
752                                  }                                  } else                  // what remains here is up or down
                                 else // what remains here is up or down  
753                                  {                                  {
754                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty, 2);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
755                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty, 1);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
756                                  }                                  }
757    
758                                  if (iDirection)                                  if (iDirection) {
759                                  {       bDirection+=iDirection;                                          bDirection += iDirection;
760                                          startx=currMV->x; starty=currMV->y;                                          start_x = currMV->x;
761                                  }                                          start_y = currMV->y;
762                          }                          }
763                          else //about to quit, eh? not so fast....                          } else                          //about to quit, eh? not so fast....
                         {  
                                 switch (bDirection)  
764                                  {                                  {
765                                    switch (bDirection) {
766                                  case 2:                                  case 2:
767                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
768                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                           start_y - iDiamondSize, 2 + 4);
769                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
770                                                                                             start_y + iDiamondSize, 2 + 8);
771                                          break;                                          break;
772                                  case 1:                                  case 1:
773                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);  
774                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
775                                                                                             start_y - iDiamondSize, 1 + 4);
776                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
777                                                                                             start_y + iDiamondSize, 1 + 8);
778                                          break;                                          break;
779                                  case 2+4:                                  case 2+4:
780                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
781                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                                                                           start_y - iDiamondSize, 1 + 4);
782                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
783                                                                                             start_y - iDiamondSize, 2 + 4);
784                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
785                                                                                             start_y + iDiamondSize, 2 + 8);
786                                          break;                                          break;
787                                  case 4:                                  case 4:
788                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
789                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                                                                           start_y - iDiamondSize, 2 + 4);
790                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
791                                                                                             start_y - iDiamondSize, 1 + 4);
792                                          break;                                          break;
793                                  case 8:                                  case 8:
794                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
795                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                           start_y + iDiamondSize, 2 + 8);
796                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
797                                                                                             start_y + iDiamondSize, 1 + 8);
798                                          break;                                          break;
799                                  case 1+4:                                  case 1+4:
800                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
801                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                                                                           start_y + iDiamondSize, 1 + 8);
802                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
803                                                                                             start_y - iDiamondSize, 1 + 4);
804                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
805                                                                                             start_y - iDiamondSize, 2 + 4);
806                                          break;                                          break;
807                                  case 2+8:                                  case 2+8:
808                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
809                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                           start_y - iDiamondSize, 1 + 4);
810                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
811                                                                                             start_y + iDiamondSize, 1 + 8);
812                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
813                                                                                             start_y + iDiamondSize, 2 + 8);
814                                          break;                                          break;
815                                  case 1+8:                                  case 1+8:
816                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
817                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                           start_y - iDiamondSize, 2 + 4);
818                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
819                                                                                             start_y + iDiamondSize, 2 + 8);
820                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
821                                                                                             start_y + iDiamondSize, 1 + 8);
822                                          break;                                          break;
823                                  default: //1+2+4+8 == we didn't find anything at all                                  default: //1+2+4+8 == we didn't find anything at all
824                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
825                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                           start_y - iDiamondSize, 1 + 4);
826                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
827                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                           start_y + iDiamondSize, 1 + 8);
828                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
829                                                                                             start_y - iDiamondSize, 2 + 4);
830                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
831                                                                                             start_y + iDiamondSize, 2 + 8);
832                                          break;                                          break;
833                                  }                                  }
834                                  if (!iDirection) break; //ok, the end. really                                  if (!iDirection)
835                                  else                                          break;          //ok, the end. really
836                                  {       bDirection=iDirection;                                  else {
837                                          startx=currMV->x; starty=currMV->y;                                          bDirection = iDirection;
838                                            start_x = currMV->x;
839                                            start_y = currMV->y;
840                                  }                                  }
841                          }                          }
842                  }                  }
# Line 912  Line 845 
845          return iMinSAD;          return iMinSAD;
846  }  }
847    
848  int32_t AdvDiamond8_MainSearch(  #define CHECK_MV16_F_INTERPOL(X,Y) { \
849          const uint8_t * const pRef,    if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
850        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
851      { \
852        iSAD = sad16bi( cur, \
853                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
854                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
855                            iEdgedWidth); \
856        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
857        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
858        if (iSAD < iMinSAD) \
859        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); } } \
860    }
861    
862    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y) { \
863      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
864        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
865      { \
866        iSAD = sad16bi( cur, \
867                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
868                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
869                            iEdgedWidth); \
870        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
871        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
872        if (iSAD < iMinSAD) \
873        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); iFound=0;} } \
874    }
875    
876    #define CHECK_MV16_B_INTERPOL(X,Y) { \
877      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
878        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
879      { \
880        iSAD = sad16bi( cur, \
881                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
882                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
883                            iEdgedWidth); \
884        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
885        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
886        if (iSAD < iMinSAD) \
887        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); } } \
888    }
889    
890    #define CHECK_MV16_B_INTERPOL_FOUND(X,Y) { \
891      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
892        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
893      { \
894        iSAD = sad16bi( cur, \
895                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
896                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
897                            iEdgedWidth); \
898        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
899        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
900        if (iSAD < iMinSAD) \
901        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); iFound=0;} } \
902    }
903    
904    int32_t
905    Diamond16_InterpolMainSearch(const uint8_t * const f_pRef,
906                                                             const uint8_t * const f_pRefH,
907                                                             const uint8_t * const f_pRefV,
908                                                             const uint8_t * const f_pRefHV,
909    
910                                                             const uint8_t * const cur,
911    
912                                                             const uint8_t * const b_pRef,
913                                                             const uint8_t * const b_pRefH,
914                                                             const uint8_t * const b_pRefV,
915                                                             const uint8_t * const b_pRefHV,
916    
917                                                             const int x,
918                                                             const int y,
919    
920                                                             const int f_start_x,
921                                                             const int f_start_y,
922                                                             const int b_start_x,
923                                                             const int b_start_y,
924    
925                                                             int iMinSAD,
926                                                             VECTOR * const f_currMV,
927                                                             VECTOR * const b_currMV,
928    
929                                                             const int f_center_x,
930                                                             const int f_center_y,
931                                                             const int b_center_x,
932                                                             const int b_center_y,
933    
934                                                             const int32_t f_min_dx,
935                                                             const int32_t f_max_dx,
936                                                             const int32_t f_min_dy,
937                                                             const int32_t f_max_dy,
938    
939                                                             const int32_t b_min_dx,
940                                                             const int32_t b_max_dx,
941                                                             const int32_t b_min_dy,
942                                                             const int32_t b_max_dy,
943    
944                                                             const int32_t iEdgedWidth,
945                                                             const int32_t iDiamondSize,
946    
947                                                             const int32_t f_iFcode,
948                                                             const int32_t b_iFcode,
949    
950                                                             const int32_t iQuant,
951                                                             int iFound)
952    {
953    /* Do a diamond search around given starting point, return SAD of best */
954    
955            int32_t iSAD;
956    
957            VECTOR f_backupMV;
958            VECTOR b_backupMV;
959    
960            f_currMV->x = f_start_x;
961            f_currMV->y = f_start_y;
962            b_currMV->x = b_start_x;
963            b_currMV->y = b_start_y;
964    
965            do
966            {
967                    iFound = 1;
968    
969                    f_backupMV = *f_currMV;
970    
971                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x - iDiamondSize, f_backupMV.y);
972                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x + iDiamondSize, f_backupMV.y);
973                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y - iDiamondSize);
974                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y + iDiamondSize);
975    
976                    b_backupMV = *b_currMV;
977    
978                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x - iDiamondSize, b_backupMV.y);
979                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x + iDiamondSize, b_backupMV.y);
980                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y - iDiamondSize);
981                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y + iDiamondSize);
982    
983            } while (!iFound);
984    
985            return iMinSAD;
986    }
987    
988    /* Sorry, these MACROS really got too large... I'll turn them into function soon! */
989    
990    #define CHECK_MV16_DIRECT_FOUND(X,Y) \
991            if ( (X)>=(-32) && (X)<=(31) && ((Y)>=-32) && ((Y)<=31) ) \
992            { int k;\
993            VECTOR mvs,b_mvs;       \
994            iSAD = 0;\
995            for (k = 0; k < 4; k++) {       \
996                                            mvs.x = (int32_t) ((TRB * directmv[k].x) / TRD + (X));          \
997                        b_mvs.x = (int32_t) (((X) == 0)                                                     \
998                                                                                    ? ((TRB - TRD) * directmv[k].x) / TRD   \
999                                                : mvs.x - directmv[k].x);                           \
1000                                                                                                                                                                    \
1001                        mvs.y = (int32_t) ((TRB * directmv[k].y) / TRD + (Y));              \
1002                            b_mvs.y = (int32_t) (((Y) == 0)                                                         \
1003                                                                                    ? ((TRB - TRD) * directmv[k].y) / TRD   \
1004                                                : mvs.y - directmv[k].y);                           \
1005                                                                                                                                                                    \
1006      if ( (mvs.x <= max_dx) && (mvs.x >= min_dx) \
1007        && (mvs.y <= max_dy) && (mvs.y >= min_dy)  \
1008            && (b_mvs.x <= max_dx) && (b_mvs.x >= min_dx)  \
1009        && (b_mvs.y <= max_dy) && (b_mvs.y >= min_dy) ) { \
1010                iSAD += sad8bi( cur + 8*(k&1) + 8*(k>>1)*iEdgedWidth,                                                                                                       \
1011                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1012                                            mvs.x, mvs.y, iEdgedWidth),                                                             \
1013                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1014                                            b_mvs.x, b_mvs.y, iEdgedWidth),                                                         \
1015                            iEdgedWidth); \
1016                    }       \
1017            else    \
1018                    iSAD = 65535;   \
1019            } \
1020            iSAD += calc_delta_16((X),(Y), 1, iQuant);\
1021            if (iSAD < iMinSAD) \
1022                {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iFound=0; } \
1023    }
1024    
1025    
1026    
1027    int32_t
1028    Diamond16_DirectMainSearch(
1029                                            const uint8_t * const f_pRef,
1030                                            const uint8_t * const f_pRefH,
1031                                            const uint8_t * const f_pRefV,
1032                                            const uint8_t * const f_pRefHV,
1033    
1034                                            const uint8_t * const cur,
1035    
1036                                            const uint8_t * const b_pRef,
1037                                            const uint8_t * const b_pRefH,
1038                                            const uint8_t * const b_pRefV,
1039                                            const uint8_t * const b_pRefHV,
1040    
1041                                            const int x,
1042                                            const int y,
1043    
1044                                            const int TRB,
1045                                            const int TRD,
1046    
1047                                        const int start_x,
1048                                        const int start_y,
1049    
1050                                        int iMinSAD,
1051                                        VECTOR * const currMV,
1052                                            const VECTOR * const directmv,
1053    
1054                                        const int32_t min_dx,
1055                                            const int32_t max_dx,
1056                                            const int32_t min_dy,
1057                                            const int32_t max_dy,
1058    
1059                                            const int32_t iEdgedWidth,
1060                                            const int32_t iDiamondSize,
1061    
1062                                            const int32_t iQuant,
1063                                            int iFound)
1064    {
1065    /* Do a diamond search around given starting point, return SAD of best */
1066    
1067            int32_t iSAD;
1068    
1069            VECTOR backupMV;
1070    
1071            currMV->x = start_x;
1072            currMV->y = start_y;
1073    
1074    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1075    
1076            do
1077            {
1078                    iFound = 1;
1079    
1080                    backupMV = *currMV;
1081    
1082                    CHECK_MV16_DIRECT_FOUND(backupMV.x - iDiamondSize, backupMV.y);
1083                    CHECK_MV16_DIRECT_FOUND(backupMV.x + iDiamondSize, backupMV.y);
1084                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y - iDiamondSize);
1085                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y + iDiamondSize);
1086    
1087            } while (!iFound);
1088    
1089            return iMinSAD;
1090    }
1091    
1092    
1093    int32_t
1094    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1095          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1096          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1097          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1098          const uint8_t * const cur,          const uint8_t * const cur,
1099          const int x, const int y,                                             const int x,
1100          int32_t startx, int32_t starty,                                             const int y,
1101          int32_t iMinSAD,                                             const int start_xi,
1102                                               const int start_yi,
1103                                               int iMinSAD,
1104          VECTOR * const currMV,          VECTOR * const currMV,
1105          const VECTOR * const pmv,                                             const int center_x,
1106          const int32_t min_dx, const int32_t max_dx,                                             const int center_y,
1107          const int32_t min_dy, const int32_t max_dy,                                             const int32_t min_dx,
1108                                               const int32_t max_dx,
1109                                               const int32_t min_dy,
1110                                               const int32_t max_dy,
1111          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1112          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1113          const int32_t iFcode,          const int32_t iFcode,
# Line 933  Line 1116 
1116  {  {
1117    
1118          int32_t iSAD;          int32_t iSAD;
1119            int start_x = start_xi, start_y = start_yi;
1120    
1121  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1122    
1123          if (iDirection)          if (iDirection) {
1124          {                  CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1125                  CHECK_MV8_CANDIDATE(startx-iDiamondSize, starty);                  CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1126                  CHECK_MV8_CANDIDATE(startx+iDiamondSize, starty);                  CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1127                  CHECK_MV8_CANDIDATE(startx, starty-iDiamondSize);                  CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1128                  CHECK_MV8_CANDIDATE(startx, starty+iDiamondSize);          } else {
         }  
         else  
         {  
1129                  int bDirection = 1+2+4+8;                  int bDirection = 1+2+4+8;
1130                  do  
1131                  {                  do {
1132                          iDirection = 0;                          iDirection = 0;
1133                          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)                          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)
1134                                  CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize,starty,1);                                  CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1135    
1136                          if (bDirection&2)                          if (bDirection&2)
1137                                  CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize,starty,2);                                  CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1138    
1139                          if (bDirection&4)                          if (bDirection&4)
1140                                  CHECK_MV8_CANDIDATE_DIR(startx,starty-iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1141    
1142                          if (bDirection&8)                          if (bDirection&8)
1143                                  CHECK_MV8_CANDIDATE_DIR(startx,starty+iDiamondSize,8);                                  CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1144    
1145                          /* now we're doing diagonal checks near our candidate */                          /* now we're doing diagonal checks near our candidate */
1146    
# Line 967  Line 1148 
1148                          {                          {
1149                                  bDirection = iDirection;                                  bDirection = iDirection;
1150                                  iDirection = 0;                                  iDirection = 0;
1151                                  startx=currMV->x; starty=currMV->y;                                  start_x = currMV->x;
1152                                    start_y = currMV->y;
1153                                  if (bDirection & 3) //our candidate is left or right                                  if (bDirection & 3) //our candidate is left or right
1154                                  {                                  {
1155                                          CHECK_MV8_CANDIDATE_DIR(startx,starty+iDiamondSize, 8);                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1156                                          CHECK_MV8_CANDIDATE_DIR(startx,starty-iDiamondSize, 4);                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1157                                  }                                  } else                  // what remains here is up or down
                                 else // what remains here is up or down  
1158                                  {                                  {
1159                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty, 2);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1160                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty, 1);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1161                                  }                                  }
1162    
1163                                  if (iDirection)                                  if (iDirection) {
1164                                  {       bDirection+=iDirection;                                          bDirection += iDirection;
1165                                          startx=currMV->x; starty=currMV->y;                                          start_x = currMV->x;
1166                                  }                                          start_y = currMV->y;
1167                          }                          }
1168                          else //about to quit, eh? not so fast....                          } else                          //about to quit, eh? not so fast....
                         {  
                                 switch (bDirection)  
1169                                  {                                  {
1170                                    switch (bDirection) {
1171                                  case 2:                                  case 2:
1172                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1173                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                          start_y - iDiamondSize, 2 + 4);
1174                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1175                                                                                            start_y + iDiamondSize, 2 + 8);
1176                                          break;                                          break;
1177                                  case 1:                                  case 1:
1178                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1179                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                          start_y - iDiamondSize, 1 + 4);
1180                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1181                                                                                            start_y + iDiamondSize, 1 + 8);
1182                                          break;                                          break;
1183                                  case 2+4:                                  case 2+4:
1184                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1185                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                                                                          start_y - iDiamondSize, 1 + 4);
1186                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1187                                                                                            start_y - iDiamondSize, 2 + 4);
1188                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1189                                                                                            start_y + iDiamondSize, 2 + 8);
1190                                          break;                                          break;
1191                                  case 4:                                  case 4:
1192                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1193                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                                                                          start_y - iDiamondSize, 2 + 4);
1194                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1195                                                                                            start_y - iDiamondSize, 1 + 4);
1196                                          break;                                          break;
1197                                  case 8:                                  case 8:
1198                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1199                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                          start_y + iDiamondSize, 2 + 8);
1200                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1201                                                                                            start_y + iDiamondSize, 1 + 8);
1202                                          break;                                          break;
1203                                  case 1+4:                                  case 1+4:
1204                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1205                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                                                                          start_y + iDiamondSize, 1 + 8);
1206                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1207                                                                                            start_y - iDiamondSize, 1 + 4);
1208                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1209                                                                                            start_y - iDiamondSize, 2 + 4);
1210                                          break;                                          break;
1211                                  case 2+8:                                  case 2+8:
1212                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1213                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                          start_y - iDiamondSize, 1 + 4);
1214                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1215                                                                                            start_y + iDiamondSize, 1 + 8);
1216                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1217                                                                                            start_y + iDiamondSize, 2 + 8);
1218                                          break;                                          break;
1219                                  case 1+8:                                  case 1+8:
1220                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1221                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                          start_y - iDiamondSize, 2 + 4);
1222                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1223                                                                                            start_y + iDiamondSize, 2 + 8);
1224                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1225                                                                                            start_y + iDiamondSize, 1 + 8);
1226                                          break;                                          break;
1227                                  default: //1+2+4+8 == we didn't find anything at all                                  default: //1+2+4+8 == we didn't find anything at all
1228                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1229                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                          start_y - iDiamondSize, 1 + 4);
1230                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1231                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                          start_y + iDiamondSize, 1 + 8);
1232                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1233                                                                                            start_y - iDiamondSize, 2 + 4);
1234                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1235                                                                                            start_y + iDiamondSize, 2 + 8);
1236                                          break;                                          break;
1237                                  }                                  }
1238                                  if (!(iDirection)) break; //ok, the end. really                                  if (!(iDirection))
1239                                  else                                          break;          //ok, the end. really
1240                                  {       bDirection=iDirection;                                  else {
1241                                          startx=currMV->x; starty=currMV->y;                                          bDirection = iDirection;
1242                                            start_x = currMV->x;
1243                                            start_y = currMV->y;
1244                                  }                                  }
1245                          }                          }
1246                  }                  }
# Line 1044  Line 1250 
1250  }  }
1251    
1252    
1253  int32_t Full8_MainSearch(  int32_t
1254                                          const uint8_t * const pRef,  Full8_MainSearch(const uint8_t * const pRef,
1255                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1256                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1257                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1258                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1259                                          const int x, const int y,                                   const int x,
1260                                          int32_t startx, int32_t starty,                                   const int y,
1261                                          int32_t iMinSAD,                             const int start_x,
1262                               const int start_y,
1263                               int iMinSAD,
1264                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1265                                          const VECTOR * const pmv,                             const int center_x,
1266                                          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1267                                          const int32_t min_dy, const int32_t max_dy,                                   const int32_t min_dx,
1268                                     const int32_t max_dx,
1269                                     const int32_t min_dy,
1270                                     const int32_t max_dy,
1271                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
1272                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
1273                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 1066  Line 1277 
1277          int32_t iSAD;          int32_t iSAD;
1278          int32_t dx,dy;          int32_t dx,dy;
1279          VECTOR backupMV;          VECTOR backupMV;
1280          backupMV.x = startx;  
1281          backupMV.y = starty;          backupMV.x = start_x;
1282            backupMV.y = start_y;
1283    
1284          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
1285                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 1076  Line 1288 
1288          return iMinSAD;          return iMinSAD;
1289  }  }
1290    
1291    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1292    
1293    int32_t
1294  int32_t Halfpel16_Refine(  Halfpel16_Refine(const uint8_t * const pRef,
         const uint8_t * const pRef,  
1295          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1296          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1297          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1298          const uint8_t * const cur,          const uint8_t * const cur,
1299          const int x, const int y,                                   const int x,
1300                                     const int y,
1301          VECTOR * const currMV,          VECTOR * const currMV,
1302          int32_t iMinSAD,          int32_t iMinSAD,
1303          const VECTOR * const pmv,                             const int center_x,
1304          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1305          const int32_t min_dy, const int32_t max_dy,                                   const int32_t min_dx,
1306                                     const int32_t max_dx,
1307                                     const int32_t min_dy,
1308                                     const int32_t max_dy,
1309          const int32_t iFcode,          const int32_t iFcode,
1310          const int32_t iQuant,          const int32_t iQuant,
1311          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1114  Line 1330 
1330  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1331    
1332    
1333  int32_t PMVfastSearch16(  
1334                                          const uint8_t * const pRef,  int32_t
1335    PMVfastSearch16(const uint8_t * const pRef,
1336                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1337                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1338                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1339                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1340                                          const int x, const int y,                                  const int x,
1341                                    const int y,
1342                                    const int start_x,      /* start is searched first, so it should contain the most */
1343                                    const int start_y,  /* likely motion vector for this block */
1344                                    const int center_x,     /* center is from where length of MVs is measured */
1345                                    const int center_y,
1346                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1347                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1348                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1154  Line 1376 
1376    
1377          MainSearch16FuncPtr MainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
1378    
 //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
1379          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1380    
1381          static int32_t threshA,threshB;          int32_t threshA, threshB;
1382          int32_t bPredEq;          int32_t bPredEq;
1383          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1384    
1385  /* Get maximum range */  /* Get maximum range */
1386          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,
1387                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1388    
1389  /* 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 */
1390    
1391          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1392          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1393          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1394          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1395          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1396          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1397    
1398          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1399            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1400    
1401          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1402                  threshA =  512;                  threshA =  512;
1403                  threshB = 1024;                  threshB = 1024;
1404            } else {
         }  
         else  
         {  
1405                  threshA = psad[0];                  threshA = psad[0];
1406                  threshB = threshA+256;                  threshB = threshA+256;
1407                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1408                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1409                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1410                            threshA = 1024;
1411                    if (threshB > 1792)
1412                            threshB = 1792;
1413          }          }
1414    
1415          iFound=0;          iFound=0;
# Line 1201  Line 1421 
1421     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1422  */  */
1423    
1424          *currMV=pmv[0];         /* current best := prediction */          currMV->x = start_x;
1425          if (!(MotionFlags & PMV_HALFPEL16 ))          currMV->y = start_y;
1426          {       /* This should NOT be necessary! */  
1427            if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
1428                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1429                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1430          }          }
1431    
1432          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1433                  currMV->x=max_dx;                  currMV->x=max_dx;
1434          }          }
1435          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1436                  currMV->x=min_dx;                  currMV->x=min_dx;
1437          }          }
1438          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1439                  currMV->y=max_dy;                  currMV->y=max_dy;
1440          }          }
1441          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1442                  currMV->y=min_dy;                  currMV->y=min_dy;
1443          }          }
1444    
1445          iMinSAD = sad16( cur,          iMinSAD =
1446                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1447                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1448          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1449            iMinSAD +=
1450          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1451          {                                            (uint8_t) iFcode, iQuant);
1452                  if (iMinSAD < 2*iQuant) // high chances for SKIP-mode  
1453                  {          if ((iMinSAD < 256) ||
1454                          if (!MVzero(*currMV))                  ((MVequal(*currMV, prevMB->mvs[0])) &&
1455                     ((int32_t) iMinSAD < prevMB->sad16))) {
1456                    if (iMinSAD < (int)(2 * iQuant))        // high chances for SKIP-mode
1457                          {                          {
1458                            if (!MVzero(*currMV)) {
1459                                  iMinSAD += MV16_00_BIAS;                                  iMinSAD += MV16_00_BIAS;
1460                                  CHECK_MV16_ZERO;                // (0,0) saves space for letterboxed pictures                                  CHECK_MV16_ZERO;                // (0,0) saves space for letterboxed pictures
1461                                  iMinSAD -= MV16_00_BIAS;                                  iMinSAD -= MV16_00_BIAS;
# Line 1291  Line 1511 
1511    
1512          if (!MVzero(pmv[1]))          if (!MVzero(pmv[1]))
1513          if (!MVequal(pmv[1],prevMB->mvs[0]))          if (!MVequal(pmv[1],prevMB->mvs[0]))
1514          if (!MVequal(pmv[1],pmv[0]))                          if (!MVequal(pmv[1], pmv[0])) {
1515          {                                  if (!(MotionFlags & PMV_HALFPEL16)) {
1516                  if (!(MotionFlags & PMV_HALFPEL16 ))                                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
1517                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
1518                  }                  }
1519    
1520                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1521          }          }
   
1522  // top neighbour, if allowed  // top neighbour, if allowed
1523          if (!MVzero(pmv[2]))          if (!MVzero(pmv[2]))
1524          if (!MVequal(pmv[2],prevMB->mvs[0]))          if (!MVequal(pmv[2],prevMB->mvs[0]))
1525          if (!MVequal(pmv[2],pmv[0]))          if (!MVequal(pmv[2],pmv[0]))
1526          if (!MVequal(pmv[2],pmv[1]))                                  if (!MVequal(pmv[2], pmv[1])) {
1527          {                                          if (!(MotionFlags & PMV_HALFPEL16)) {
1528                  if (!(MotionFlags & PMV_HALFPEL16 ))                                                  pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
1529                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
1530                  }                  }
1531                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
# Line 1318  Line 1535 
1535                  if (!MVequal(pmv[3],prevMB->mvs[0]))                  if (!MVequal(pmv[3],prevMB->mvs[0]))
1536                  if (!MVequal(pmv[3],pmv[0]))                  if (!MVequal(pmv[3],pmv[0]))
1537                  if (!MVequal(pmv[3],pmv[1]))                  if (!MVequal(pmv[3],pmv[1]))
1538                  if (!MVequal(pmv[3],pmv[2]))                                                                          if (!MVequal(pmv[3], pmv[2])) {
1539                  {                                                                                  if (!(MotionFlags & PMV_HALFPEL16)) {
1540                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                                                          pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
1541                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
1542                          }                          }
1543                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1544                                                                                                                             pmv[3].y);
1545                  }                  }
1546          }          }
1547    
1548          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )          if ((MVzero(*currMV)) &&
1549                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1550                  iMinSAD -= MV16_00_BIAS;                  iMinSAD -= MV16_00_BIAS;
1551    
1552    
# Line 1336  Line 1554 
1554     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.
1555  */  */
1556    
1557          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1558          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1559                     ((int32_t) iMinSAD < prevMB->sad16))) {
1560                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1561                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1562                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1357  Line 1576 
1576    
1577          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
1578                  MainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
1579          else          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
                 if (MotionFlags & PMV_ADVANCEDDIAMOND16)  
1580                          MainSearchPtr = AdvDiamond16_MainSearch;                          MainSearchPtr = AdvDiamond16_MainSearch;
1581                  else                  else
1582                          MainSearchPtr = Diamond16_MainSearch;                          MainSearchPtr = Diamond16_MainSearch;
1583    
1584          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1585    
1586    
1587  /* 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 */
1588          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1589                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1590                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1591                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1592                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1593                                                      iQuant, iFound);
1594    
1595          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1596                  *currMV = newMV;                  *currMV = newMV;
1597                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1598          }          }
1599    
1600          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1601  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1602    
1603                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1604                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1605                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1606                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1607                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1608                                                                      iDiamondSize, iFcode, iQuant, iFound);
1609    
1610                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1611                          *currMV = newMV;                          *currMV = newMV;
1612                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1613                  }                  }
1614                  }                  }
1615    
1616                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1617                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1618                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1619                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1620                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1621                                                                      iEdgedWidth, iDiamondSize, iFcode,
1622                                                                      iQuant, iFound);
1623    
1624                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1625                          *currMV = newMV;                          *currMV = newMV;
1626                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1627                  }                  }
# Line 1414  Line 1634 
1634    
1635  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1636          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1637                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1638                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1639                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1640                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1641    
1642  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1643          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1644          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1645          return iMinSAD;          return iMinSAD;
1646  }  }
1647    
# Line 1430  Line 1650 
1650    
1651    
1652    
1653  int32_t Diamond8_MainSearch(  int32_t
1654          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1655          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1656          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1657          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1658          const uint8_t * const cur,          const uint8_t * const cur,
1659          const int x, const int y,                                          const int x,
1660          int32_t startx, int32_t starty,                                          const int y,
1661                                            const int32_t start_x,
1662                                            const int32_t start_y,
1663          int32_t iMinSAD,          int32_t iMinSAD,
1664          VECTOR * const currMV,          VECTOR * const currMV,
1665          const VECTOR * const pmv,                                          const int center_x,
1666          const int32_t min_dx, const int32_t max_dx,                                          const int center_y,
1667          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1668                                            const int32_t max_dx,
1669                                            const int32_t min_dy,
1670                                            const int32_t max_dy,
1671          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1672          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1673          const int32_t iFcode,          const int32_t iFcode,
# Line 1452  Line 1677 
1677  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1678    
1679          int32_t iDirection=0;          int32_t iDirection=0;
1680            int32_t iDirectionBackup;
1681          int32_t iSAD;          int32_t iSAD;
1682          VECTOR backupMV;          VECTOR backupMV;
1683          backupMV.x = startx;  
1684          backupMV.y = starty;          backupMV.x = start_x;
1685            backupMV.y = start_y;
1686    
1687  /* 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 */
1688    
# Line 1464  Line 1691 
1691          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1692          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1693    
1694          if (iDirection)          if (iDirection) {
1695                  while (!iFound)                  while (!iFound) {
                 {  
1696                          iFound = 1;                          iFound = 1;
1697                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1698                            iDirectionBackup = iDirection;
1699    
1700                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1701                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1702                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1703                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1704                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1705                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1706                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1707                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1708                                                                                      backupMV.y - iDiamondSize, 3);
1709                            if (iDirectionBackup != 3)
1710                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1711                                                                                      backupMV.y + iDiamondSize, 4);
1712                    }
1713            } else {
1714                    currMV->x = start_x;
1715                    currMV->y = start_y;
1716                  }                  }
1717          else          return iMinSAD;
1718    }
1719    
1720    
1721    
1722    
1723    int32_t
1724    Square8_MainSearch(const uint8_t * const pRef,
1725                                       const uint8_t * const pRefH,
1726                                       const uint8_t * const pRefV,
1727                                       const uint8_t * const pRefHV,
1728                                       const uint8_t * const cur,
1729                                       const int x,
1730                                       const int y,
1731                                       const int32_t start_x,
1732                                       const int32_t start_y,
1733                                       int32_t iMinSAD,
1734                                       VECTOR * const currMV,
1735                                       const int center_x,
1736                                       const int center_y,
1737                                       const int32_t min_dx,
1738                                       const int32_t max_dx,
1739                                       const int32_t min_dy,
1740                                       const int32_t max_dy,
1741                                       const int32_t iEdgedWidth,
1742                                       const int32_t iDiamondSize,
1743                                       const int32_t iFcode,
1744                                       const int32_t iQuant,
1745                                       int iFound)
1746          {          {
1747                  currMV->x = startx;  /* Do a square search around given starting point, return SAD of best */
1748                  currMV->y = starty;  
1749            int32_t iDirection = 0;
1750            int32_t iSAD;
1751            VECTOR backupMV;
1752    
1753            backupMV.x = start_x;
1754            backupMV.y = start_y;
1755    
1756    /* It's one search with full square pattern, and new parts for all following diamonds */
1757    
1758    /*   new direction are extra, so 1-4 is normal diamond
1759          537
1760          1*2
1761          648
1762    */
1763    
1764            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1765            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1766            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1767            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1768    
1769            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1770                                                             backupMV.y - iDiamondSize, 5);
1771            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1772                                                             backupMV.y + iDiamondSize, 6);
1773            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1774                                                             backupMV.y - iDiamondSize, 7);
1775            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1776                                                             backupMV.y + iDiamondSize, 8);
1777    
1778    
1779            if (iDirection) {
1780                    while (!iFound) {
1781                            iFound = 1;
1782                            backupMV = *currMV;
1783    
1784                            switch (iDirection) {
1785                            case 1:
1786                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1787                                                                                       backupMV.y, 1);
1788                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1789                                                                                     backupMV.y - iDiamondSize, 5);
1790                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1791                                                                                     backupMV.y - iDiamondSize, 7);
1792                                    break;
1793                            case 2:
1794                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1795                                                                                     2);
1796                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1797                                                                                     backupMV.y + iDiamondSize, 6);
1798                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1799                                                                                     backupMV.y + iDiamondSize, 8);
1800                                    break;
1801    
1802                            case 3:
1803                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1804                                                                                     4);
1805                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1806                                                                                     backupMV.y - iDiamondSize, 7);
1807                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1808                                                                                     backupMV.y + iDiamondSize, 8);
1809                                    break;
1810    
1811                            case 4:
1812                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1813                                                                                     3);
1814                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1815                                                                                     backupMV.y - iDiamondSize, 5);
1816                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1817                                                                                     backupMV.y + iDiamondSize, 6);
1818                                    break;
1819    
1820                            case 5:
1821                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1822                                                                                     1);
1823                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1824                                                                                     3);
1825                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1826                                                                                     backupMV.y - iDiamondSize, 5);
1827                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1828                                                                                     backupMV.y + iDiamondSize, 6);
1829                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1830                                                                                     backupMV.y - iDiamondSize, 7);
1831                                    break;
1832    
1833                            case 6:
1834                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1835                                                                                     2);
1836                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1837                                                                                     3);
1838    
1839                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1840                                                                                     backupMV.y - iDiamondSize, 5);
1841                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1842                                                                                     backupMV.y + iDiamondSize, 6);
1843                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1844                                                                                     backupMV.y + iDiamondSize, 8);
1845    
1846                                    break;
1847    
1848                            case 7:
1849                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1850                                                                                       backupMV.y, 1);
1851                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1852                                                                                     4);
1853                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1854                                                                                     backupMV.y - iDiamondSize, 5);
1855                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1856                                                                                     backupMV.y - iDiamondSize, 7);
1857                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1858                                                                                     backupMV.y + iDiamondSize, 8);
1859                                    break;
1860    
1861                            case 8:
1862                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1863                                                                                     2);
1864                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1865                                                                                     4);
1866                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1867                                                                                     backupMV.y + iDiamondSize, 6);
1868                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1869                                                                                     backupMV.y - iDiamondSize, 7);
1870                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1871                                                                                     backupMV.y + iDiamondSize, 8);
1872                                    break;
1873                            default:
1874                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1875                                                                                     1);
1876                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1877                                                                                     2);
1878                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1879                                                                                     3);
1880                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1881                                                                                     4);
1882    
1883                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1884                                                                                     backupMV.y - iDiamondSize, 5);
1885                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1886                                                                                     backupMV.y + iDiamondSize, 6);
1887                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1888                                                                                     backupMV.y - iDiamondSize, 7);
1889                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1890                                                                                     backupMV.y + iDiamondSize, 8);
1891                                    break;
1892                            }
1893                    }
1894            } else {
1895                    currMV->x = start_x;
1896                    currMV->y = start_y;
1897          }          }
1898          return iMinSAD;          return iMinSAD;
1899  }  }
1900    
1901  int32_t Halfpel8_Refine(  
1902          const uint8_t * const pRef,  
1903    
1904    
1905    int32_t
1906    Halfpel8_Refine_c(const uint8_t * const pRef,
1907          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1908          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1909          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1910          const uint8_t * const cur,          const uint8_t * const cur,
1911          const int x, const int y,                                    const int x,
1912                                      const int y,
1913          VECTOR * const currMV,          VECTOR * const currMV,
1914          int32_t iMinSAD,          int32_t iMinSAD,
1915          const VECTOR * const pmv,                                    const int center_x,
1916          const int32_t min_dx, const int32_t max_dx,                                    const int center_y,
1917          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
1918                                      const int32_t max_dx,
1919                                      const int32_t min_dy,
1920                                      const int32_t max_dy,
1921          const int32_t iFcode,          const int32_t iFcode,
1922          const int32_t iQuant,          const int32_t iQuant,
1923          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1523  Line 1942 
1942    
1943  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1944    
1945  int32_t PMVfastSearch8(  int32_t
1946                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1947                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1948                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1949                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1950                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1951                                          const int x, const int y,                             const int x,
1952                                          const int start_x, const int start_y,                             const int y,
1953                               const int start_x,
1954                               const int start_y,
1955                                    const int center_x,
1956                                    const int center_y,
1957                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1958                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1959                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1563  Line 1986 
1986  //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1987          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1988    
1989          static int32_t threshA,threshB;           int32_t threshA, threshB;
1990          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1991          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1992    
# Line 1576  Line 1999 
1999          startMV.y = start_y;          startMV.y = start_y;
2000    
2001          /* Get maximum range */          /* Get maximum range */
2002          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2003                    x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2004    
2005          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
2006          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2007            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2008            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2009            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2010          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
2011    
2012          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
2013            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
2014    
2015          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2016                  threshA =  512/4;                  threshA =  512/4;
2017                  threshB = 1024/4;                  threshB = 1024/4;
2018    
2019          }          } else {
2020          else                  threshA = psad[0] / 4;  /* good estimate? */
         {  
                 threshA = psad[0]/4;                    /* good estimate */  
2021                  threshB = threshA+256/4;                  threshB = threshA+256/4;
2022                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
2023                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
2024                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
2025                            threshA = 1024 / 4;
2026                    if (threshB > 1792 / 4)
2027                            threshB = 1792 / 4;
2028          }          }
2029    
2030          iFound=0;          iFound=0;
# Line 1616  Line 2039 
2039    
2040  // Prepare for main loop  // Prepare for main loop
2041    
2042  //      if (MotionFlags & PMV_USESQUARES8)    if (MotionFlags & PMV_USESQUARES8)
2043  //              MainSearchPtr = Square8_MainSearch;        MainSearchPtr = Square8_MainSearch;
2044  //      else    else
2045    
2046          if (MotionFlags & PMV_ADVANCEDDIAMOND8)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2047                  MainSearchPtr = AdvDiamond8_MainSearch;                  MainSearchPtr = AdvDiamond8_MainSearch;
# Line 1628  Line 2051 
2051    
2052          *currMV = startMV;          *currMV = startMV;
2053    
2054          iMinSAD = sad8( cur,          iMinSAD =
2055                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2056                          iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2057          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode, iQuant);                                                  iEdgedWidth), iEdgedWidth);
2058            iMinSAD +=
2059                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2060                                             (uint8_t) iFcode, iQuant);
2061    
2062          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))
2063                                  && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )                                                                  && ((int32_t) iMinSAD <
2064          {                                                                          prevMB->sad8[iSubBlock]))) {
2065                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2066                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2067                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1673  Line 2099 
2099  // the median prediction might be even better than mv16  // the median prediction might be even better than mv16
2100    
2101          if (!MVequal(pmv[0],startMV))          if (!MVequal(pmv[0],startMV))
2102                  CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);                  CHECK_MV8_CANDIDATE(center_x, center_y);
2103    
2104  // (0,0) if needed  // (0,0) if needed
2105          if (!MVzero(pmv[0]))          if (!MVzero(pmv[0]))
# Line 1684  Line 2110 
2110          if (!MVzero(prevMB->mvs[iSubBlock]))          if (!MVzero(prevMB->mvs[iSubBlock]))
2111          if (!MVequal(prevMB->mvs[iSubBlock],startMV))          if (!MVequal(prevMB->mvs[iSubBlock],startMV))
2112          if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))          if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))
2113          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);                                  CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
2114                                                                            prevMB->mvs[iSubBlock].y);
2115    
2116          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2117          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2118                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2119                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2120                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2121                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
2122                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
2123          }          }
2124    
   
2125  // left neighbour, if allowed and needed  // left neighbour, if allowed and needed
2126          if (!MVzero(pmv[1]))          if (!MVzero(pmv[1]))
2127          if (!MVequal(pmv[1],startMV))          if (!MVequal(pmv[1],startMV))
2128          if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))          if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))
2129          if (!MVequal(pmv[1],pmv[0]))                                  if (!MVequal(pmv[1], pmv[0])) {
2130          {                                          if (!(MotionFlags & PMV_HALFPEL8)) {
2131                  if (!(MotionFlags & PMV_HALFPEL8 ))                                                  pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2132                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2133                  }                  }
2134                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2135          }          }
   
2136  // top neighbour, if allowed and needed  // top neighbour, if allowed and needed
2137          if (!MVzero(pmv[2]))          if (!MVzero(pmv[2]))
2138          if (!MVequal(pmv[2],startMV))          if (!MVequal(pmv[2],startMV))
2139          if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))          if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))
2140          if (!MVequal(pmv[2],pmv[0]))          if (!MVequal(pmv[2],pmv[0]))
2141          if (!MVequal(pmv[2],pmv[1]))                                          if (!MVequal(pmv[2], pmv[1])) {
2142          {                                                  if (!(MotionFlags & PMV_HALFPEL8)) {
2143                  if (!(MotionFlags & PMV_HALFPEL8 ))                                                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2144                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2145                  }                  }
2146                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
# Line 1727  Line 2151 
2151          if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))          if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))
2152          if (!MVequal(pmv[3],pmv[0]))          if (!MVequal(pmv[3],pmv[0]))
2153          if (!MVequal(pmv[3],pmv[1]))          if (!MVequal(pmv[3],pmv[1]))
2154          if (!MVequal(pmv[3],pmv[2]))                                                                                          if (!MVequal(pmv[3], pmv[2])) {
2155                  {                                                                                                  if (!
2156                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                                                          (MotionFlags &
2157                          {       pmv[3].x = EVEN(pmv[3].x);                                                                                                           PMV_HALFPEL8)) {
2158                                                                                                            pmv[3].x = EVEN(pmv[3].x);
2159                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2160                          }                          }
2161                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
2162                                                                                                                                            pmv[3].y);
2163                  }                  }
2164          }          }
2165    
2166          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )          if ((MVzero(*currMV)) &&
2167                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2168                  iMinSAD -= MV8_00_BIAS;                  iMinSAD -= MV8_00_BIAS;
2169    
2170    
# Line 1745  Line 2172 
2172     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.
2173  */  */
2174    
2175          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2176          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2177                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2178                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2179                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2180                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1766  Line 2194 
2194          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2195    
2196  /* 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 */
2197          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2198                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2199                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2200                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2201                                                      iQuant, iFound);
2202    
2203          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2204                  *currMV = newMV;                  *currMV = newMV;
2205                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2206          }          }
2207    
2208          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2209  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
2210    
2211                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2212                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2213                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2214                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2215                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2216                                                                      iDiamondSize, iFcode, iQuant, iFound);
2217    
2218                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2219                          *currMV = newMV;                          *currMV = newMV;
2220                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2221                  }                  }
2222                  }                  }
2223    
2224                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2225                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2226                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2227                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2228                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2229                                                                      iQuant, iFound);
2230    
2231                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2232                          *currMV = newMV;                          *currMV = newMV;
2233                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2234                  }                  }
# Line 1814  Line 2241 
2241    
2242  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
2243          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2244                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2245                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2246                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2247                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2248    
2249    
2250  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
2251          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2252          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2253    
2254          return iMinSAD;          return iMinSAD;
2255  }  }
2256    
2257  int32_t EPZSSearch16(  int32_t
2258                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2259                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2260                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2261                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2262                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2263                                          const int x, const int y,                           const int x,
2264                             const int y,
2265                            const int start_x,
2266                            const int start_y,
2267                            const int center_x,
2268                            const int center_y,
2269                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2270                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2271                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1864  Line 2296 
2296          int32_t psad[8];          int32_t psad[8];
2297    
2298          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2299    
2300  //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2301          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
2302          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
2303    
2304          static int32_t thresh2;           int32_t thresh2;
2305          int32_t bPredEq;          int32_t bPredEq;
2306          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2307    
2308          MainSearch16FuncPtr MainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2309    
2310          if (oldMBs == NULL)          if (oldMBs == NULL) {
2311          {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2312  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2313          }          }
2314          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2315    
2316  /* Get maximum range */  /* Get maximum range */
2317          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,
2318                          x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
2319    
2320          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
2321          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2322            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2323            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2324            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2325          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2326            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2327          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2328    
2329  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2330          MinSAD=SAD          MinSAD=SAD
# Line 1902  Line 2335 
2335    
2336  // Prepare for main loop  // Prepare for main loop
2337    
2338          *currMV=pmv[0];         /* current best := median prediction */          currMV->x = start_x;
2339          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2340          {  
2341            if (!(MotionFlags & PMV_HALFPEL16)) {
2342                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2343                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2344          }          }
# Line 1920  Line 2354 
2354    
2355  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2356    
2357          iMinSAD = sad16( cur,          iMinSAD =
2358                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2359                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2360          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2361            iMinSAD +=
2362                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2363                                              (uint8_t) iFcode, iQuant);
2364    
2365  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2366          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD < 256) ||
2367                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2368                     ((int32_t) iMinSAD < prevMB->sad16))) {
2369                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2370                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2371                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1942  Line 2380 
2380  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2381  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
2382    
2383          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2384                  thresh2 =  512;                  thresh2 =  512;
2385          }          } else {
         else  
         {  
2386  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
2387    
2388                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1959  Line 2394 
2394    
2395    
2396  // left neighbour, if allowed  // left neighbour, if allowed
2397          if (x != 0)          if (x != 0) {
2398          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2399                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2400                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2401                  }                  }
2402                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2403          }          }
   
2404  // top neighbour, if allowed  // top neighbour, if allowed
2405          if (y != 0)          if (y != 0) {
2406          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2407                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2408                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2409                  }                  }
2410                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
2411    
2412  // top right neighbour, if allowed  // top right neighbour, if allowed
2413                  if ((uint32_t)x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
2414                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2415                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2416                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2417                          }                          }
2418                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1993  Line 2424 
2424  */  */
2425    
2426          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2427                  || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2428                  {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2429                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2430                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2431                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 2015  Line 2446 
2446    
2447  // top neighbour  // top neighbour
2448          if (y != 0)          if (y != 0)
2449                  CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2450                                                             (prevMB - iWcount)->mvs[0].y);
2451    
2452  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2453    
# Line 2024  Line 2456 
2456    
2457  // bottom neighbour, dito  // bottom neighbour, dito
2458          if ((uint32_t)y != iHcount-1)          if ((uint32_t)y != iHcount-1)
2459                  CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2460                                                             (prevMB + iWcount)->mvs[0].y);
2461    
2462  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2463          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2) {
                 {  
2464                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2465                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2466                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 2039  Line 2471 
2471    
2472          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2473    
2474            if (MotionFlags & PMV_USESQUARES16)
2475                    MainSearchPtr = Square16_MainSearch;
2476            else
2477             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2478                    MainSearchPtr = AdvDiamond16_MainSearch;
2479            else
2480                    MainSearchPtr = Diamond16_MainSearch;
2481    
2482  /* 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 */
2483    
2484          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2485                          x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2486                          currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2487                          2, iFcode, iQuant, 0);                                                    min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2488    
2489          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2490                  *currMV = newMV;                  *currMV = newMV;
2491                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2492          }          }
2493    
2494    
2495          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
2496  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2497    
2498                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2499                  {                          iSAD =
2500                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2501                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2502                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2503                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2504                  }                  }
2505    
2506                  if (iSAD < iMinSAD)                  if (iSAD < iMinSAD) {
                 {  
2507                          *currMV = newMV;                          *currMV = newMV;
2508                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2509                  }                  }
2510    
2511                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2512                  {                          iSAD =
2513                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2514                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2515                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
                         pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);  
2516    
2517                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2518                                  *currMV = newMV;                                  *currMV = newMV;
2519                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2520                          }                          }
# Line 2090  Line 2525 
2525    
2526  EPZS16_Terminate_with_Refine:  EPZS16_Terminate_with_Refine:
2527          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
2528                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2529                                  x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2530                                  currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2531                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
2532    
2533  EPZS16_Terminate_without_Refine:  EPZS16_Terminate_without_Refine:
2534    
2535          *oldMB = *prevMB;          *oldMB = *prevMB;
2536    
2537          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2538          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2539          return iMinSAD;          return iMinSAD;
2540  }  }
2541    
2542    
2543  int32_t EPZSSearch8(  int32_t
2544                                          const uint8_t * const pRef,  EPZSSearch8(const uint8_t * const pRef,
2545                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2546                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2547                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2548                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2549                                          const int x, const int y,                          const int x,
2550                                          const int start_x, const int start_y,                          const int y,
2551                            const int start_x,
2552                            const int start_y,
2553                            const int center_x,
2554                            const int center_y,
2555                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2556                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2557                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 2155  Line 2594 
2594          MainSearch8FuncPtr MainSearchPtr;          MainSearch8FuncPtr MainSearchPtr;
2595    
2596  /* Get maximum range */  /* Get maximum range */
2597          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2598                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2599    
2600  /* 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 */
2601    
2602          if (!(MotionFlags & PMV_HALFPEL8 ))          if (!(MotionFlags & PMV_HALFPEL8)) {
2603          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2604            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2605            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2606            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2607          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2608            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2609          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2610    
2611    
2612  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 2180  Line 2619 
2619  // Prepare for main loop  // Prepare for main loop
2620    
2621    
2622          if (!(MotionFlags & PMV_HALFPEL8))          if (!(MotionFlags & PMV_HALFPEL8)) {
         {  
2623                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2624                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2625          }          }
# Line 2198  Line 2636 
2636  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2637    
2638    
2639          iMinSAD = sad8( cur,          iMinSAD =
2640                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2641                  iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2642          iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                  iEdgedWidth), iEdgedWidth);
2643            iMinSAD +=
2644                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2645                                             (uint8_t) iFcode, iQuant);
2646    
2647    
2648  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2649          if (iMinSAD < 256/4 )          if (iMinSAD < 256 / 4) {
                 {  
2650                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2651                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2652                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 2223  Line 2663 
2663          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
2664    
2665  // left neighbour, if allowed  // left neighbour, if allowed
2666          if (psad[1] != MV_MAX_ERROR)          if (psad[1] != MV_MAX_ERROR) {
2667          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2668                  if (!(MotionFlags & PMV_HALFPEL8 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2669                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2670                  }                  }
2671                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2672          }          }
   
2673  // top neighbour, if allowed  // top neighbour, if allowed
2674          if (psad[2] != MV_MAX_ERROR)          if (psad[2] != MV_MAX_ERROR) {
2675          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2676                  if (!(MotionFlags & PMV_HALFPEL8 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2677                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2678                  }                  }
2679                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2680    
2681  // top right neighbour, if allowed  // top right neighbour, if allowed
2682                  if (psad[3] != MV_MAX_ERROR)                  if (psad[3] != MV_MAX_ERROR) {
2683                  {                          if (!(MotionFlags & PMV_HALFPEL8)) {
2684                          if (!(MotionFlags & PMV_HALFPEL8 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2685                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2686                          }                          }
2687                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 2263  Line 2699 
2699     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2700  */  */
2701    
2702          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
                 {  
2703                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2704                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2705                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 2280  Line 2715 
2715    
2716  /* default: use best prediction as starting point for one call of EPZS_MainSearch */  /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2717    
2718  /* // there is no EPZS^2 for inter4v at the moment  // there is no EPZS^2 for inter4v at the moment
2719    
2720          if (MotionFlags & PMV_USESQUARES8)          if (MotionFlags & PMV_USESQUARES8)
2721                  MainSearchPtr = Square8_MainSearch;                  MainSearchPtr = Square8_MainSearch;
2722          else          else
 */  
   
 //      if (MotionFlags & PMV_USESQUARES8)  
 //              MainSearchPtr = Square8_MainSearch;  
 //      else  
2723    
2724          if (MotionFlags & PMV_ADVANCEDDIAMOND8)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2725                  MainSearchPtr = AdvDiamond8_MainSearch;                  MainSearchPtr = AdvDiamond8_MainSearch;
2726          else          else
2727                  MainSearchPtr = Diamond8_MainSearch;                  MainSearchPtr = Diamond8_MainSearch;
2728    
2729          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2730                  x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2731                  currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2732                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2733                  iDiamondSize, iFcode, iQuant, 0);                                                    iQuant, 0);
2734    
2735    
2736          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2737                  *currMV = newMV;                  *currMV = newMV;
2738                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2739          }          }
2740    
2741          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2742  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2743    
2744                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2745                  {                          iSAD =
2746                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2747                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2748                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2749                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2750    
2751                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2752                                  *currMV = newMV;                                  *currMV = newMV;
2753                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2754                          }                          }
2755                  }                  }
2756    
2757                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2758                  {                          iSAD =
2759                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2760                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2761                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2762                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, 0);
2763    
2764                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2765                                  *currMV = newMV;                                  *currMV = newMV;
2766                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2767                          }                          }
# Line 2346  Line 2772 
2772    
2773  EPZS8_Terminate_with_Refine:  EPZS8_Terminate_with_Refine:
2774          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2775                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2776                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2777                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2778                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2779    
2780  EPZS8_Terminate_without_Refine:  EPZS8_Terminate_without_Refine:
2781    
2782          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2783          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2784          return iMinSAD;          return iMinSAD;
2785  }  }
2786    
2787    
2788    
2789    int32_t
2790    PMVfastIntSearch16(const uint8_t * const pRef,
2791                                    const uint8_t * const pRefH,
2792                                    const uint8_t * const pRefV,
2793                                    const uint8_t * const pRefHV,
2794                                    const IMAGE * const pCur,
2795                                    const int x,
2796                                    const int y,
2797                                    const int start_x,              /* start should be most likely vector */
2798                                    const int start_y,
2799                                    const int center_x,             /* center is from where length of MVs is measured */
2800                                    const int center_y,
2801                                    const uint32_t MotionFlags,
2802                                    const uint32_t iQuant,
2803                                    const uint32_t iFcode,
2804                                    const MBParam * const pParam,
2805                                    const MACROBLOCK * const pMBs,
2806                                    const MACROBLOCK * const prevMBs,
2807                                    VECTOR * const currMV,
2808                                    VECTOR * const currPMV)
2809    {
2810            const uint32_t iWcount = pParam->mb_width;
2811            const int32_t iWidth = pParam->width;
2812            const int32_t iHeight = pParam->height;
2813            const int32_t iEdgedWidth = pParam->edged_width;
2814    
2815            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2816            const VECTOR zeroMV = { 0, 0 };
2817    
2818            int32_t iDiamondSize;
2819    
2820            int32_t min_dx;
2821            int32_t max_dx;
2822            int32_t min_dy;
2823            int32_t max_dy;
2824    
2825            int32_t iFound;
2826    
2827  /* ***********************************************************          VECTOR newMV;
2828          bvop motion estimation          VECTOR backupMV;
 // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)  
 ***************************************************************/  
2829    
2830            VECTOR pmv[4];
2831            int32_t psad[4];
2832    
2833  void MotionEstimationBVOP(          MainSearch16FuncPtr MainSearchPtr;
                         MBParam * const pParam,  
                         FRAMEINFO * const frame,  
2834    
2835                          // forward (past) reference          MACROBLOCK *const prevMB = (MACROBLOCK *const)prevMBs + x + y * iWcount;
2836                          const MACROBLOCK * const f_mbs,          MACROBLOCK *const pMB = (MACROBLOCK *const)(pMBs + x + y * iWcount);
2837                      const IMAGE * const f_ref,  
2838                          const IMAGE * const f_refH,          int32_t threshA, threshB;
2839                      const IMAGE * const f_refV,          int32_t bPredEq;
2840                          const IMAGE * const f_refHV,          int32_t iMinSAD, iSAD;
2841                          // backward (future) reference  
2842                          const MACROBLOCK * const b_mbs,  
2843                      const IMAGE * const b_ref,  /* Get maximum range */
2844                          const IMAGE * const b_refH,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2845                      const IMAGE * const b_refV,                            iFcode);
2846                          const IMAGE * const b_refHV)  
2847  {  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2848      const uint32_t mb_width = pParam->mb_width;  
2849      const uint32_t mb_height = pParam->mb_height;          if ((x == 0) && (y == 0)) {
2850          const int32_t edged_width = pParam->edged_width;                  threshA = 512;
2851                    threshB = 1024;
2852          uint32_t i,j;  
2853                    bPredEq = 0;
2854          int32_t f_sad16;                  psad[0] = psad[1] = psad[2] = psad[3] = 0;
2855          int32_t b_sad16;                  *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2856          int32_t i_sad16;  
2857          int32_t d_sad16;          } else {
2858          int32_t best_sad;  
2859                    bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2860          VECTOR pmv_dontcare;  
2861                    threshA = psad[0];
2862          // note: i==horizontal, j==vertical                  threshB = threshA + 256;
2863      for (j = 0; j < mb_height; j++)                  if (threshA < 512)
2864          {                          threshA = 512;
2865                  for (i = 0; i < mb_width; i++)                  if (threshA > 1024)
2866                  {                          threshA = 1024;
2867                          MACROBLOCK *mb = &frame->mbs[i + j*mb_width];                  if (threshB > 1792)
2868                          const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];                          threshB = 1792;
2869                          const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];  
2870                    *currMV = pmv[0];                       /* current best := prediction */
                         if (b_mb->mode == MODE_INTER  
                                 && b_mb->cbp == 0  
                                 && b_mb->mvs[0].x == 0  
                                 && b_mb->mvs[0].y == 0)  
                         {  
                                 mb->mode = MODE_NOT_CODED;  
                                 mb->mvs[0].x = 0;  
                                 mb->mvs[0].y = 0;  
                                 mb->b_mvs[0].x = 0;  
                                 mb->b_mvs[0].y = 0;  
                                 continue;  
2871                          }                          }
2872    
2873            iFound = 0;
2874    
2875    /* Step 4: Calculate SAD around the Median prediction.
2876       MinSAD=SAD
2877       If Motion Vector equal to Previous frame motion vector
2878       and MinSAD<PrevFrmSAD goto Step 10.
2879       If SAD<=256 goto Step 10.
2880    */
2881    
2882                          // forward search          if (currMV->x > max_dx) {
2883                          f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                  currMV->x = EVEN(max_dx);
2884                                                  &frame->image,          }
2885                                                  i, j,          if (currMV->x < min_dx) {
2886                                                  frame->motion_flags,  frame->quant, frame->fcode,                  currMV->x = EVEN(min_dx);
2887                                                  pParam,          }
2888                                                  f_mbs, f_mbs /* todo */,          if (currMV->y > max_dy) {
2889                                                  &mb->mvs[0], &pmv_dontcare);    // ignore pmv                  currMV->y = EVEN(max_dy);
2890            }
2891                          // backward search          if (currMV->y < min_dy) {
2892                          b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                  currMV->y = EVEN(min_dy);
2893                                                  &frame->image,          }
                                                 i, j,  
                                                 frame->motion_flags,  frame->quant, frame->bcode,  
                                                 pParam,  
                                                 b_mbs, b_mbs, /* todo */  
                                                 &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv  
   
                         // interpolate search (simple, but effective)  
                         i_sad16 = sad16bi_c(  
                                         frame->image.y + i*16 + j*16*edged_width,  
                                         get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,  
                                                 i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),  
                                         get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,  
                                                 i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),  
                                         edged_width);  
   
                         // TODO: direct search  
                         // predictor + range of [-32,32]  
                         d_sad16 = 65535;  
2894    
2895            iMinSAD =
2896                    sad16(cur,
2897                              get_iref_mv(pRef, x, y, 16, currMV,
2898                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2899            iMinSAD +=
2900                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2901                                              (uint8_t) iFcode, iQuant);
2902    
2903                          if (f_sad16 < b_sad16)          if ((iMinSAD < 256) ||
2904                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2905                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2906                    if (iMinSAD < (int)(2 * iQuant))        // high chances for SKIP-mode
2907                          {                          {
2908                                  best_sad = f_sad16;                          if (!MVzero(*currMV)) {
2909                                  mb->mode = MODE_FORWARD;                                  iMinSAD += MV16_00_BIAS;
2910                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2911                                    iMinSAD -= MV16_00_BIAS;
2912                            }
2913                          }                          }
2914    
2915                    if (MotionFlags & PMV_EARLYSTOP16)
2916                            goto PMVfastInt16_Terminate_with_Refine;
2917            }
2918    
2919    
2920    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2921       vector of the median.
2922       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2923    */
2924    
2925            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2926                    iFound = 2;
2927    
2928    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2929       Otherwise select large Diamond Search.
2930    */
2931    
2932            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2933                    iDiamondSize = 2;               // halfpel units!
2934                          else                          else
2935                          {                  iDiamondSize = 4;               // halfpel units!
2936                                  best_sad = b_sad16;  
2937                                  mb->mode = MODE_BACKWARD;  /*
2938       Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2939       Also calculate (0,0) but do not subtract offset.
2940       Let MinSAD be the smallest SAD up to this point.
2941       If MV is (0,0) subtract offset.
2942    */
2943    
2944    // (0,0) is often a good choice
2945    
2946            if (!MVzero(pmv[0]))
2947                    CHECK_MV16_ZERO;
2948    
2949    // previous frame MV is always possible
2950    
2951            if (!MVzero(prevMB->i_mvs[0]))
2952                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2953                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2954    
2955    // left neighbour, if allowed
2956    
2957            if (!MVzero(pmv[1]))
2958                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2959                            if (!MVequal(pmv[1], pmv[0]))
2960                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2961    
2962    // top neighbour, if allowed
2963            if (!MVzero(pmv[2]))
2964                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
2965                            if (!MVequal(pmv[2], pmv[0]))
2966                                    if (!MVequal(pmv[2], pmv[1]))
2967                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2968    
2969    // top right neighbour, if allowed
2970                                            if (!MVzero(pmv[3]))
2971                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
2972                                                            if (!MVequal(pmv[3], pmv[0]))
2973                                                                    if (!MVequal(pmv[3], pmv[1]))
2974                                                                            if (!MVequal(pmv[3], pmv[2]))
2975                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
2976                                                                                                                             pmv[3].y);
2977    
2978            if ((MVzero(*currMV)) &&
2979                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2980                    iMinSAD -= MV16_00_BIAS;
2981    
2982    
2983    /* Step 6: If MinSAD <= thresa goto Step 10.
2984       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2985    */
2986    
2987            if ((iMinSAD <= threshA) ||
2988                    (MVequal(*currMV, prevMB->i_mvs[0]) &&
2989                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2990    
2991                    if (MotionFlags & PMV_EARLYSTOP16)
2992                            goto PMVfastInt16_Terminate_with_Refine;
2993                          }                          }
2994    
2995                          if (i_sad16 < best_sad)  
2996                          {  /************ (Diamond Search)  **************/
2997                                  best_sad = i_sad16;  /*
2998                                  mb->mode = MODE_INTERPOLATE;     Step 7: Perform Diamond search, with either the small or large diamond.
2999       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
3000       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
3001       If center then goto step 10.
3002       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
3003       Refine by using small diamond and goto step 10.
3004    */
3005    
3006            if (MotionFlags & PMV_USESQUARES16)
3007                    MainSearchPtr = Square16_MainSearch;
3008            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
3009                    MainSearchPtr = AdvDiamond16_MainSearch;
3010            else
3011                    MainSearchPtr = Diamond16_MainSearch;
3012    
3013            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
3014    
3015    
3016    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
3017            iSAD =
3018                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
3019                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
3020                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
3021                                                      iQuant, iFound);
3022    
3023            if (iSAD < iMinSAD) {
3024                    *currMV = newMV;
3025                    iMinSAD = iSAD;
3026                          }                          }
3027    
3028                          if (d_sad16 < best_sad)          if (MotionFlags & PMV_EXTSEARCH16) {
3029                          {  /* extended: search (up to) two more times: orignal prediction and (0,0) */
3030                                  best_sad = d_sad16;  
3031                                  mb->mode = MODE_DIRECT;                  if (!(MVequal(pmv[0], backupMV))) {
3032                            iSAD =
3033                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
3034                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
3035                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
3036                                                                      iDiamondSize, iFcode, iQuant, iFound);
3037    
3038                            if (iSAD < iMinSAD) {
3039                                    *currMV = newMV;
3040                                    iMinSAD = iSAD;
3041                            }
3042                          }                          }
3043    
3044                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
3045                            iSAD =
3046                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
3047                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
3048                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
3049                                                                      iQuant, iFound);
3050    
3051                            if (iSAD < iMinSAD) {
3052                                    *currMV = newMV;
3053                                    iMinSAD = iSAD;
3054                            }
3055                  }                  }
3056          }          }
3057    
3058    /*
3059       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
3060    */
3061    
3062    PMVfastInt16_Terminate_with_Refine:
3063    
3064            pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
3065            pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
3066    
3067            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
3068                    iMinSAD =
3069                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
3070                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
3071                                                             iFcode, iQuant, iEdgedWidth);
3072    
3073            pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
3074    
3075            currPMV->x = currMV->x - center_x;
3076            currPMV->y = currMV->y - center_y;
3077            return iMinSAD;
3078  }  }
3079    

Legend:
Removed from v.181  
changed lines
  Added in v.476

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