[svn] / branches / dev-api-4 / xvidcore / src / motion / motion_est.c Repository:
ViewVC logotype

Diff of /branches/dev-api-4/xvidcore/src/motion/motion_est.c

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

revision 184, Mon May 27 18:07:38 2002 UTC revision 486, Mon Sep 16 21:41:20 2002 UTC
# Line 1  Line 1 
1  /**************************************************************************  /*****************************************************************************
2   *   *
3   *  Modifications:   *  XVID MPEG-4 VIDEO CODEC
4     *  - Motion Estimation module -
5   *   *
6   *      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  
47    
 /* 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);  
   
   
 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,
# Line 280  Line 138 
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,                          predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
                                                  x, y, current->motion_flags, current->quant, current->fcode,  
                                                  pParam, pMBs, prevMBs, &pMB->mv16, &pMB->pmvs[0]);  
157    
158                          if (0 < (pMB->sad16 - MV16_INTER_BIAS))                          pMB->sad16 =
159                          {                                  SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
160                                                     x, y, predMV.x, predMV.y, predMV.x, predMV.y,
161                                                     current->motion_flags, current->quant,
162                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
163                                                     &pMB->pmvs[0]);
164    
165                            if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
166                                  int32_t deviation;                                  int32_t deviation;
                                 deviation = dev16(pCurrent->y + x*16 + y*16*pParam->edged_width, pParam->edged_width);  
167    
168                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS))                                  deviation =
169                                  {                                          dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
170                                                      pParam->edged_width);
171    
172                                    if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
173                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
174                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = zeroMV;                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
175                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;                                                  pMB->mvs[3] = zeroMV;
176                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
177                                                    pMB->sad8[3] = 0;
178    
179                                          iIntra++;                                          iIntra++;
180                                          if (iIntra >= iLimit)                                          if (iIntra >= iLimit)
# Line 319  Line 186 
186    
187                          pmv = pMB->pmvs[0];                          pmv = pMB->pmvs[0];
188                          if (current->global_flags & XVID_INTER4V)                          if (current->global_flags & XVID_INTER4V)
189                                  if ( (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE) )                                  if ((!(current->global_flags & XVID_LUMIMASKING) ||
190                                  {                                           pMB->dquant == NO_CHANGE)) {
191                                          int32_t sad8 = IMV16X16 * current->quant; if (sad8 < pMB->sad16)                                          int32_t sad8 = IMV16X16 * current->quant;
192    
193                                          sad8 += pMB->sad8[0]            = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                          if (sad8 < pMB->sad16) {
194                                                                                                                          2*x, 2*y, pMB->mv16.x, pMB->mv16.y,                                                  sad8 += pMB->sad8[0] =
195                                                                                                                          current->motion_flags, current->quant, current->fcode,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
196                                                                                                                          pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);                                                                          pCurrent, 2 * x, 2 * y,
197                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
198                                          if (sad8 < pMB->sad16)                                                                          current->motion_flags,
199                                                  sad8 += pMB->sad8[1]    = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                                          current->quant, current->fcode, pParam,
200                                                                                                                          2*x+1, 2*y, pMB->mv16.x, pMB->mv16.y,                                                                          pMBs, prevMBs, &pMB->mvs[0],
201                                                                                                                          current->motion_flags, current->quant, current->fcode,                                                                          &pMB->pmvs[0]);
202                                                                                                                          pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);                                          }
203                                            if (sad8 < pMB->sad16) {
204                                          if (sad8 < pMB->sad16)  
205                                                  sad8 += pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                  predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
206                                                                                                                          2*x, 2*y+1, pMB->mv16.x, pMB->mv16.y,                                                  sad8 += pMB->sad8[1] =
207                                                                                                                          current->motion_flags, current->quant, current->fcode,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
208                                                                                                                          pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);                                                                          pCurrent, 2 * x + 1, 2 * y,
209                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
210                                          if (sad8 < pMB->sad16)                                                                          current->motion_flags,
211                                                  sad8 += pMB->sad8[3]    = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                                          current->quant, current->fcode, pParam,
212                                                                                                                          2*x+1, 2*y+1, pMB->mv16.x, pMB->mv16.y,                                                                          pMBs, prevMBs, &pMB->mvs[1],
213                                                                                                                          current->motion_flags, current->quant, current->fcode,                                                                          &pMB->pmvs[1]);
214                                                                                                                          pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);                                          }
215                                            if (sad8 < pMB->sad16) {
216                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
217                                                    sad8 += pMB->sad8[2] =
218                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
219                                                                            pCurrent, 2 * x, 2 * y + 1,
220                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
221                                                                            current->motion_flags,
222                                                                            current->quant, current->fcode, pParam,
223                                                                            pMBs, prevMBs, &pMB->mvs[2],
224                                                                            &pMB->pmvs[2]);
225                                            }
226                                            if (sad8 < pMB->sad16) {
227                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
228                                                    sad8 += pMB->sad8[3] =
229                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
230                                                                            pCurrent, 2 * x + 1, 2 * y + 1,
231                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
232                                                                            current->motion_flags,
233                                                                            current->quant, current->fcode, pParam,
234                                                                            pMBs, prevMBs,
235                                                                            &pMB->mvs[3],
236                                                                            &pMB->pmvs[3]);
237                                            }
238    
239                                          /* decide: MODE_INTER or MODE_INTER4V                                          /* decide: MODE_INTER or MODE_INTER4V
240                                                  mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v                                                  mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
241                                          */                                          */
242    
243                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16) {
                                         {  
244                                                  pMB->mode = MODE_INTER4V;                                                  pMB->mode = MODE_INTER4V;
245                              pMB->sad8[0] *= 4;                              pMB->sad8[0] *= 4;
246                                                  pMB->sad8[1] *= 4;                                                  pMB->sad8[1] *= 4;
# Line 365  Line 254 
254                                  pMB->mode = MODE_INTER;                                  pMB->mode = MODE_INTER;
255                                  pMB->pmvs[0] = pmv; /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */                                  pMB->pmvs[0] = pmv; /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
256                                  pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;                                  pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
257                                  pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = pMB->sad16;                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
258                                    pMB->sad16;
259                  }                  }
260                            }
261    
262                  return 0;                  return 0;
263  }  }
264    
265    
266  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
267    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
268      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
269    { \    { \
270      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \
271      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
272      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
273      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
274  }  }
275    
276  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
277      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); \
278      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);\
279      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
280      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
281  }  }
# Line 393  Line 285 
285      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
286    { \    { \
287      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
288      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
289      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
290      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
291  }  }
# Line 403  Line 295 
295      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
296    { \    { \
297      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
298      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
299      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
300      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
301  }  }
# Line 413  Line 305 
305      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
306    { \    { \
307      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
308      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
309      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
310      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
311  }  }
# Line 421  Line 313 
313    
314  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
315    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \
316    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\    iSAD += calc_delta_8(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
317    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
318    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
319  }  }
# Line 429  Line 321 
321  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
322    { \    { \
323      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); \
324      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);\
325      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
326      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
327  }  }
# Line 439  Line 331 
331      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
332    { \    { \
333      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
334      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
335      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
336      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
337  }  }
# Line 449  Line 341 
341      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
342    { \    { \
343      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
344      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
345      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
346      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
347  }  }
# Line 459  Line 351 
351      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
352    { \    { \
353      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
354      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
355      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
356      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
357  }  }
# Line 485  Line 377 
377          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
378          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
379          int32_t iSAD;          int32_t iSAD;
380          int32_t pred_x,pred_y;          VECTOR pred;
381    
382    
383          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
384    
385          iSAD = sad16( cur,          iSAD = sad16( cur,
386                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
# Line 497  Line 390 
390    
391          currMV->x = 0;          currMV->x = 0;
392          currMV->y = 0;          currMV->y = 0;
393          currPMV->x = -pred_x;          currPMV->x = -pred.x;
394          currPMV->y = -pred_y;          currPMV->y = -pred.y;
395    
396          return iSAD;          return iSAD;
397    
398  }  }
399  */  */
400    
401  int32_t Diamond16_MainSearch(  int32_t
402          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
403          const uint8_t * const pRefH,          const uint8_t * const pRefH,
404          const uint8_t * const pRefV,          const uint8_t * const pRefV,
405          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
406          const uint8_t * const cur,          const uint8_t * const cur,
407          const int x, const int y,                                           const int x,
408          int32_t startx, int32_t starty,                                           const int y,
409          int32_t iMinSAD,                                           const int start_x,
410                                             const int start_y,
411                                             int iMinSAD,
412          VECTOR * const currMV,          VECTOR * const currMV,
413          const VECTOR * const pmv,                                           const int center_x,
414          const int32_t min_dx, const int32_t max_dx,                                           const int center_y,
415          const int32_t min_dy, const int32_t max_dy,                                           const int32_t min_dx,
416                                             const int32_t max_dx,
417                                             const int32_t min_dy,
418                                             const int32_t max_dy,
419          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
420          const int32_t iDiamondSize,          const int32_t iDiamondSize,
421          const int32_t iFcode,          const int32_t iFcode,
# Line 527  Line 425 
425  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
426    
427          int32_t iDirection=0;          int32_t iDirection=0;
428            int32_t iDirectionBackup;
429          int32_t iSAD;          int32_t iSAD;
430          VECTOR backupMV;          VECTOR backupMV;
431          backupMV.x = startx;  
432          backupMV.y = starty;          backupMV.x = start_x;
433            backupMV.y = start_y;
434    
435  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
436    
# Line 539  Line 439 
439          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
440          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
441    
442          if (iDirection)          if (iDirection) {
443                  while (!iFound)                  while (!iFound) {
                 {  
444                          iFound = 1;                          iFound = 1;
445                          backupMV=*currMV;                          backupMV=*currMV;
446                            iDirectionBackup = iDirection;
447    
448                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
449                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
450                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
451                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
452                          if ( iDirection != 4)                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
453                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                     backupMV.y, 2);
454                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
455                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
456                  }                                                                                     backupMV.y - iDiamondSize, 3);
457          else                          if (iDirectionBackup != 3)
458          {                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
459                  currMV->x = startx;                                                                                     backupMV.y + iDiamondSize, 4);
460                  currMV->y = starty;                  }
461            } else {
462                    currMV->x = start_x;
463                    currMV->y = start_y;
464          }          }
465          return iMinSAD;          return iMinSAD;
466  }  }
467    
468  int32_t Square16_MainSearch(  int32_t
469                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
470                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
471                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
472                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
473                                          const uint8_t * const cur,                                          const uint8_t * const cur,
474                                          const int x, const int y,                                          const int x,
475                                          int32_t startx, int32_t starty,                                          const int y,
476                                          int32_t iMinSAD,                                          const int start_x,
477                                            const int start_y,
478                                            int iMinSAD,
479                                          VECTOR * const currMV,                                          VECTOR * const currMV,
480                                          const VECTOR * const pmv,                                          const int center_x,
481                                          const int32_t min_dx, const int32_t max_dx,                                          const int center_y,
482                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
483                                            const int32_t max_dx,
484                                            const int32_t min_dy,
485                                            const int32_t max_dy,
486                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
487                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
488                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 586  Line 494 
494          int32_t iDirection=0;          int32_t iDirection=0;
495          int32_t iSAD;          int32_t iSAD;
496          VECTOR backupMV;          VECTOR backupMV;
497          backupMV.x = startx;  
498          backupMV.y = starty;          backupMV.x = start_x;
499            backupMV.y = start_y;
500    
501  /* It's one search with full square pattern, and new parts for all following diamonds */  /* It's one search with full square pattern, and new parts for all following diamonds */
502    
# Line 602  Line 511 
511          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
512          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
513    
514          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
515          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
516          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
517          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
518            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
519                                                             backupMV.y - iDiamondSize, 7);
520            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
521                                                             backupMV.y + iDiamondSize, 8);
522    
523    
524          if (iDirection)          if (iDirection) {
525                  while (!iFound)                  while (!iFound) {
                 {  
526                          iFound = 1;                          iFound = 1;
527                          backupMV=*currMV;                          backupMV=*currMV;
528    
529                          switch (iDirection)                          switch (iDirection) {
                         {  
530                                  case 1:                                  case 1:
531                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
532                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
533                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
534                                                                                     backupMV.y - iDiamondSize, 5);
535                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
536                                                                                     backupMV.y - iDiamondSize, 7);
537                                          break;                                          break;
538                                  case 2:                                  case 2:
539                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
540                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
541                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
542                                                                                     backupMV.y + iDiamondSize, 6);
543                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
544                                                                                     backupMV.y + iDiamondSize, 8);
545                                          break;                                          break;
546    
547                                  case 3:                                  case 3:
548                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
549                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
550                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
551                                                                                     backupMV.y - iDiamondSize, 7);
552                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
553                                                                                     backupMV.y + iDiamondSize, 8);
554                                          break;                                          break;
555    
556                                  case 4:                                  case 4:
557                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
558                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
559                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
560                                                                                     backupMV.y - iDiamondSize, 5);
561                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
562                                                                                     backupMV.y + iDiamondSize, 6);
563                                          break;                                          break;
564    
565                                  case 5:                                  case 5:
566                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
567                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
568                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
569                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
570                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
571                                                                                     backupMV.y - iDiamondSize, 5);
572                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
573                                                                                     backupMV.y + iDiamondSize, 6);
574                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
575                                                                                     backupMV.y - iDiamondSize, 7);
576                                          break;                                          break;
577    
578                                  case 6:                                  case 6:
579                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
580                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
581                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
582                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
583                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
584                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
585                                                                                     backupMV.y - iDiamondSize, 5);
586                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
587                                                                                     backupMV.y + iDiamondSize, 6);
588                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
589                                                                                     backupMV.y + iDiamondSize, 8);
590    
591                                          break;                                          break;
592    
593                                  case 7:                                  case 7:
594                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
595                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
596                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
597                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
598                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
599                                                                                     backupMV.y - iDiamondSize, 5);
600                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
601                                                                                     backupMV.y - iDiamondSize, 7);
602                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
603                                                                                     backupMV.y + iDiamondSize, 8);
604                                          break;                                          break;
605    
606                                  case 8:                                  case 8:
607                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
608                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
609                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
610                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
611                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
612                                                                                     backupMV.y + iDiamondSize, 6);
613                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
614                                                                                     backupMV.y - iDiamondSize, 7);
615                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
616                                                                                     backupMV.y + iDiamondSize, 8);
617                                          break;                                          break;
618                          default:                          default:
619                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
620                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
621                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
622                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
623                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
624                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
625                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
626                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
627                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
628                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
629                                                                                     backupMV.y - iDiamondSize, 5);
630                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
631                                                                                     backupMV.y + iDiamondSize, 6);
632                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
633                                                                                     backupMV.y - iDiamondSize, 7);
634                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
635                                                                                     backupMV.y + iDiamondSize, 8);
636                                          break;                                          break;
637                          }                          }
638                  }                  }
639          else          } else {
640                  {                  currMV->x = start_x;
641                          currMV->x = startx;                  currMV->y = start_y;
                         currMV->y = starty;  
642                  }                  }
643          return iMinSAD;          return iMinSAD;
644  }  }
645    
646    
647  int32_t Full16_MainSearch(  int32_t
648                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
649                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
650                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
651                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
652                                          const uint8_t * const cur,                                          const uint8_t * const cur,
653                                          const int x, const int y,                                    const int x,
654                                          int32_t startx, int32_t starty,                                    const int y,
655                                          int32_t iMinSAD,                                    const int start_x,
656                                      const int start_y,
657                                      int iMinSAD,
658                                          VECTOR * const currMV,                                          VECTOR * const currMV,
659                                          const VECTOR * const pmv,                                    const int center_x,
660                                          const int32_t min_dx, const int32_t max_dx,                                    const int center_y,
661                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
662                                      const int32_t max_dx,
663                                      const int32_t min_dy,
664                                      const int32_t max_dy,
665                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
666                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
667                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 716  Line 671 
671          int32_t iSAD;          int32_t iSAD;
672          int32_t dx,dy;          int32_t dx,dy;
673          VECTOR backupMV;          VECTOR backupMV;
674          backupMV.x = startx;  
675          backupMV.y = starty;          backupMV.x = start_x;
676            backupMV.y = start_y;
677    
678          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
679                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 726  Line 682 
682          return iMinSAD;          return iMinSAD;
683  }  }
684    
685  int32_t AdvDiamond16_MainSearch(  int32_t
686          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
687          const uint8_t * const pRefH,          const uint8_t * const pRefH,
688          const uint8_t * const pRefV,          const uint8_t * const pRefV,
689          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
690          const uint8_t * const cur,          const uint8_t * const cur,
691          const int x, const int y,                                                  const int x,
692          int32_t startx, int32_t starty,                                                  const int y,
693          int32_t iMinSAD,                                                  const int start_xi,
694                                                    const int start_yi,
695                                                    int iMinSAD,
696          VECTOR * const currMV,          VECTOR * const currMV,
697          const VECTOR * const pmv,                                                  const int center_x,
698          const int32_t min_dx, const int32_t max_dx,                                                  const int center_y,
699          const int32_t min_dy, const int32_t max_dy,                                                  const int32_t min_dx,
700                                                    const int32_t max_dx,
701                                                    const int32_t min_dy,
702                                                    const int32_t max_dy,
703          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
704          const int32_t iDiamondSize,          const int32_t iDiamondSize,
705          const int32_t iFcode,          const int32_t iFcode,
# Line 747  Line 708 
708  {  {
709    
710          int32_t iSAD;          int32_t iSAD;
711            int start_x = start_xi, start_y = start_yi;
712    
713  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
714    
715          if (iDirection)          if (iDirection) {
716          {                  CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
717                  CHECK_MV16_CANDIDATE(startx-iDiamondSize, starty);                  CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
718                  CHECK_MV16_CANDIDATE(startx+iDiamondSize, starty);                  CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
719                  CHECK_MV16_CANDIDATE(startx, starty-iDiamondSize);                  CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
720                  CHECK_MV16_CANDIDATE(startx, starty+iDiamondSize);          } else {
         }  
         else  
         {  
721                  int bDirection = 1+2+4+8;                  int bDirection = 1+2+4+8;
722                  do  
723                  {                  do {
724                          iDirection = 0;                          iDirection = 0;
725                          if (bDirection&1) //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)                          if (bDirection&1) //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
726                                  CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize,starty,1);                                  CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
727    
728                          if (bDirection&2)                          if (bDirection&2)
729                                  CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize,starty,2);                                  CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
730    
731                          if (bDirection&4)                          if (bDirection&4)
732                                  CHECK_MV16_CANDIDATE_DIR(startx,starty-iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
733    
734                          if (bDirection&8)                          if (bDirection&8)
735                                  CHECK_MV16_CANDIDATE_DIR(startx,starty+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
736    
737                          /* now we're doing diagonal checks near our candidate */                          /* now we're doing diagonal checks near our candidate */
738    
# Line 781  Line 740 
740                          {                          {
741                                  bDirection = iDirection;                                  bDirection = iDirection;
742                                  iDirection = 0;                                  iDirection = 0;
743                                  startx=currMV->x; starty=currMV->y;                                  start_x = currMV->x;
744                                    start_y = currMV->y;
745                                  if (bDirection & 3) //our candidate is left or right                                  if (bDirection & 3) //our candidate is left or right
746                                  {                                  {
747                                          CHECK_MV16_CANDIDATE_DIR(startx,starty+iDiamondSize, 8);                                          CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
748                                          CHECK_MV16_CANDIDATE_DIR(startx,starty-iDiamondSize, 4);                                          CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
749                                  }                                  } else                  // what remains here is up or down
                                 else // what remains here is up or down  
750                                  {                                  {
751                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty, 2);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
752                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty, 1);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
753                                  }                                  }
754    
755                                  if (iDirection)                                  if (iDirection) {
756                                  {       bDirection+=iDirection;                                          bDirection += iDirection;
757                                          startx=currMV->x; starty=currMV->y;                                          start_x = currMV->x;
758                                  }                                          start_y = currMV->y;
759                          }                          }
760                          else //about to quit, eh? not so fast....                          } else                          //about to quit, eh? not so fast....
                         {  
                                 switch (bDirection)  
761                                  {                                  {
762                                    switch (bDirection) {
763                                  case 2:                                  case 2:
764                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
765                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                           start_y - iDiamondSize, 2 + 4);
766                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
767                                                                                             start_y + iDiamondSize, 2 + 8);
768                                          break;                                          break;
769                                  case 1:                                  case 1:
770                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);  
771                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
772                                                                                             start_y - iDiamondSize, 1 + 4);
773                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
774                                                                                             start_y + iDiamondSize, 1 + 8);
775                                          break;                                          break;
776                                  case 2+4:                                  case 2+4:
777                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
778                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                                                                           start_y - iDiamondSize, 1 + 4);
779                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
780                                                                                             start_y - iDiamondSize, 2 + 4);
781                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
782                                                                                             start_y + iDiamondSize, 2 + 8);
783                                          break;                                          break;
784                                  case 4:                                  case 4:
785                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
786                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                                                                           start_y - iDiamondSize, 2 + 4);
787                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
788                                                                                             start_y - iDiamondSize, 1 + 4);
789                                          break;                                          break;
790                                  case 8:                                  case 8:
791                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
792                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                           start_y + iDiamondSize, 2 + 8);
793                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
794                                                                                             start_y + iDiamondSize, 1 + 8);
795                                          break;                                          break;
796                                  case 1+4:                                  case 1+4:
797                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
798                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                                                                           start_y + iDiamondSize, 1 + 8);
799                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
800                                                                                             start_y - iDiamondSize, 1 + 4);
801                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
802                                                                                             start_y - iDiamondSize, 2 + 4);
803                                          break;                                          break;
804                                  case 2+8:                                  case 2+8:
805                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
806                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                           start_y - iDiamondSize, 1 + 4);
807                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
808                                                                                             start_y + iDiamondSize, 1 + 8);
809                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
810                                                                                             start_y + iDiamondSize, 2 + 8);
811                                          break;                                          break;
812                                  case 1+8:                                  case 1+8:
813                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
814                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                           start_y - iDiamondSize, 2 + 4);
815                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
816                                                                                             start_y + iDiamondSize, 2 + 8);
817                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
818                                                                                             start_y + iDiamondSize, 1 + 8);
819                                          break;                                          break;
820                                  default: //1+2+4+8 == we didn't find anything at all                                  default: //1+2+4+8 == we didn't find anything at all
821                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
822                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                           start_y - iDiamondSize, 1 + 4);
823                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
824                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                           start_y + iDiamondSize, 1 + 8);
825                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
826                                                                                             start_y - iDiamondSize, 2 + 4);
827                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
828                                                                                             start_y + iDiamondSize, 2 + 8);
829                                          break;                                          break;
830                                  }                                  }
831                                  if (!iDirection) break; //ok, the end. really                                  if (!iDirection)
832                                  else                                          break;          //ok, the end. really
833                                  {       bDirection=iDirection;                                  else {
834                                          startx=currMV->x; starty=currMV->y;                                          bDirection = iDirection;
835                                            start_x = currMV->x;
836                                            start_y = currMV->y;
837                                  }                                  }
838                          }                          }
839                  }                  }
# Line 857  Line 842 
842          return iMinSAD;          return iMinSAD;
843  }  }
844    
845  int32_t AdvDiamond8_MainSearch(  #define CHECK_MV16_F_INTERPOL(X,Y) { \
846          const uint8_t * const pRef,    if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
847        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
848      { \
849        iSAD = sad16bi( cur, \
850                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
851                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
852                            iEdgedWidth); \
853        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
854        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
855        if (iSAD < iMinSAD) \
856        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); } } \
857    }
858    
859    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y) { \
860      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
861        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
862      { \
863        iSAD = sad16bi( cur, \
864                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
865                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
866                            iEdgedWidth); \
867        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
868        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
869        if (iSAD < iMinSAD) \
870        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); iFound=0;} } \
871    }
872    
873    #define CHECK_MV16_B_INTERPOL(X,Y) { \
874      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
875        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
876      { \
877        iSAD = sad16bi( cur, \
878                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
879                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
880                            iEdgedWidth); \
881        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
882        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
883        if (iSAD < iMinSAD) \
884        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); } } \
885    }
886    
887    #define CHECK_MV16_B_INTERPOL_FOUND(X,Y) { \
888      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
889        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
890      { \
891        iSAD = sad16bi( cur, \
892                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
893                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
894                            iEdgedWidth); \
895        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
896        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
897        if (iSAD < iMinSAD) \
898        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); iFound=0;} } \
899    }
900    
901    int32_t
902    Diamond16_InterpolMainSearch(const uint8_t * const f_pRef,
903                                                             const uint8_t * const f_pRefH,
904                                                             const uint8_t * const f_pRefV,
905                                                             const uint8_t * const f_pRefHV,
906    
907                                                             const uint8_t * const cur,
908    
909                                                             const uint8_t * const b_pRef,
910                                                             const uint8_t * const b_pRefH,
911                                                             const uint8_t * const b_pRefV,
912                                                             const uint8_t * const b_pRefHV,
913    
914                                                             const int x,
915                                                             const int y,
916    
917                                                             const int f_start_x,
918                                                             const int f_start_y,
919                                                             const int b_start_x,
920                                                             const int b_start_y,
921    
922                                                             int iMinSAD,
923                                                             VECTOR * const f_currMV,
924                                                             VECTOR * const b_currMV,
925    
926                                                             const int f_center_x,
927                                                             const int f_center_y,
928                                                             const int b_center_x,
929                                                             const int b_center_y,
930    
931                                                             const int32_t f_min_dx,
932                                                             const int32_t f_max_dx,
933                                                             const int32_t f_min_dy,
934                                                             const int32_t f_max_dy,
935    
936                                                             const int32_t b_min_dx,
937                                                             const int32_t b_max_dx,
938                                                             const int32_t b_min_dy,
939                                                             const int32_t b_max_dy,
940    
941                                                             const int32_t iEdgedWidth,
942                                                             const int32_t iDiamondSize,
943    
944                                                             const int32_t f_iFcode,
945                                                             const int32_t b_iFcode,
946    
947                                                             const int32_t iQuant,
948                                                             int iFound)
949    {
950    /* Do a diamond search around given starting point, return SAD of best */
951    
952            int32_t iSAD;
953    
954            VECTOR f_backupMV;
955            VECTOR b_backupMV;
956    
957            f_currMV->x = f_start_x;
958            f_currMV->y = f_start_y;
959            b_currMV->x = b_start_x;
960            b_currMV->y = b_start_y;
961    
962            do
963            {
964                    iFound = 1;
965    
966                    f_backupMV = *f_currMV;
967    
968                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x - iDiamondSize, f_backupMV.y);
969                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x + iDiamondSize, f_backupMV.y);
970                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y - iDiamondSize);
971                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y + iDiamondSize);
972    
973                    b_backupMV = *b_currMV;
974    
975                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x - iDiamondSize, b_backupMV.y);
976                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x + iDiamondSize, b_backupMV.y);
977                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y - iDiamondSize);
978                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y + iDiamondSize);
979    
980            } while (!iFound);
981    
982            return iMinSAD;
983    }
984    
985    /* Sorry, these MACROS really got too large... I'll turn them into function soon! */
986    
987    #define CHECK_MV16_DIRECT_FOUND(X,Y) \
988            if ( (X)>=(-32) && (X)<=(31) && ((Y)>=-32) && ((Y)<=31) ) \
989            { int k;\
990            VECTOR mvs,b_mvs;       \
991            iSAD = 0;\
992            for (k = 0; k < 4; k++) {       \
993                                            mvs.x = (int32_t) ((TRB * directmv[k].x) / TRD + (X));          \
994                        b_mvs.x = (int32_t) (((X) == 0)                                                     \
995                                                                                    ? ((TRB - TRD) * directmv[k].x) / TRD   \
996                                                : mvs.x - directmv[k].x);                           \
997                                                                                                                                                                    \
998                        mvs.y = (int32_t) ((TRB * directmv[k].y) / TRD + (Y));              \
999                            b_mvs.y = (int32_t) (((Y) == 0)                                                         \
1000                                                                                    ? ((TRB - TRD) * directmv[k].y) / TRD   \
1001                                                : mvs.y - directmv[k].y);                           \
1002                                                                                                                                                                    \
1003      if ( (mvs.x <= max_dx) && (mvs.x >= min_dx) \
1004        && (mvs.y <= max_dy) && (mvs.y >= min_dy)  \
1005            && (b_mvs.x <= max_dx) && (b_mvs.x >= min_dx)  \
1006        && (b_mvs.y <= max_dy) && (b_mvs.y >= min_dy) ) { \
1007                iSAD += sad8bi( cur + 8*(k&1) + 8*(k>>1)*iEdgedWidth,                                                                                                       \
1008                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1009                                            mvs.x, mvs.y, iEdgedWidth),                                                             \
1010                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1011                                            b_mvs.x, b_mvs.y, iEdgedWidth),                                                         \
1012                            iEdgedWidth); \
1013                    }       \
1014            else    \
1015                    iSAD = 65535;   \
1016            } \
1017            iSAD += calc_delta_16((X),(Y), 1, iQuant);\
1018            if (iSAD < iMinSAD) \
1019                {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iFound=0; } \
1020    }
1021    
1022    
1023    
1024    int32_t
1025    Diamond16_DirectMainSearch(
1026                                            const uint8_t * const f_pRef,
1027                                            const uint8_t * const f_pRefH,
1028                                            const uint8_t * const f_pRefV,
1029                                            const uint8_t * const f_pRefHV,
1030    
1031                                            const uint8_t * const cur,
1032    
1033                                            const uint8_t * const b_pRef,
1034                                            const uint8_t * const b_pRefH,
1035                                            const uint8_t * const b_pRefV,
1036                                            const uint8_t * const b_pRefHV,
1037    
1038                                            const int x,
1039                                            const int y,
1040    
1041                                            const int TRB,
1042                                            const int TRD,
1043    
1044                                        const int start_x,
1045                                        const int start_y,
1046    
1047                                        int iMinSAD,
1048                                        VECTOR * const currMV,
1049                                            const VECTOR * const directmv,
1050    
1051                                        const int32_t min_dx,
1052                                            const int32_t max_dx,
1053                                            const int32_t min_dy,
1054                                            const int32_t max_dy,
1055    
1056                                            const int32_t iEdgedWidth,
1057                                            const int32_t iDiamondSize,
1058    
1059                                            const int32_t iQuant,
1060                                            int iFound)
1061    {
1062    /* Do a diamond search around given starting point, return SAD of best */
1063    
1064            int32_t iSAD;
1065    
1066            VECTOR backupMV;
1067    
1068            currMV->x = start_x;
1069            currMV->y = start_y;
1070    
1071    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1072    
1073            do
1074            {
1075                    iFound = 1;
1076    
1077                    backupMV = *currMV;
1078    
1079                    CHECK_MV16_DIRECT_FOUND(backupMV.x - iDiamondSize, backupMV.y);
1080                    CHECK_MV16_DIRECT_FOUND(backupMV.x + iDiamondSize, backupMV.y);
1081                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y - iDiamondSize);
1082                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y + iDiamondSize);
1083    
1084            } while (!iFound);
1085    
1086            return iMinSAD;
1087    }
1088    
1089    
1090    int32_t
1091    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1092          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1093          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1094          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1095          const uint8_t * const cur,          const uint8_t * const cur,
1096          const int x, const int y,                                             const int x,
1097          int32_t startx, int32_t starty,                                             const int y,
1098          int32_t iMinSAD,                                             const int start_xi,
1099                                               const int start_yi,
1100                                               int iMinSAD,
1101          VECTOR * const currMV,          VECTOR * const currMV,
1102          const VECTOR * const pmv,                                             const int center_x,
1103          const int32_t min_dx, const int32_t max_dx,                                             const int center_y,
1104          const int32_t min_dy, const int32_t max_dy,                                             const int32_t min_dx,
1105                                               const int32_t max_dx,
1106                                               const int32_t min_dy,
1107                                               const int32_t max_dy,
1108          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1109          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1110          const int32_t iFcode,          const int32_t iFcode,
# Line 878  Line 1113 
1113  {  {
1114    
1115          int32_t iSAD;          int32_t iSAD;
1116            int start_x = start_xi, start_y = start_yi;
1117    
1118  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1119    
1120          if (iDirection)          if (iDirection) {
1121          {                  CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1122                  CHECK_MV8_CANDIDATE(startx-iDiamondSize, starty);                  CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1123                  CHECK_MV8_CANDIDATE(startx+iDiamondSize, starty);                  CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1124                  CHECK_MV8_CANDIDATE(startx, starty-iDiamondSize);                  CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1125                  CHECK_MV8_CANDIDATE(startx, starty+iDiamondSize);          } else {
         }  
         else  
         {  
1126                  int bDirection = 1+2+4+8;                  int bDirection = 1+2+4+8;
1127                  do  
1128                  {                  do {
1129                          iDirection = 0;                          iDirection = 0;
1130                          if (bDirection&1) //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)                          if (bDirection&1) //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
1131                                  CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize,starty,1);                                  CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1132    
1133                          if (bDirection&2)                          if (bDirection&2)
1134                                  CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize,starty,2);                                  CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1135    
1136                          if (bDirection&4)                          if (bDirection&4)
1137                                  CHECK_MV8_CANDIDATE_DIR(startx,starty-iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1138    
1139                          if (bDirection&8)                          if (bDirection&8)
1140                                  CHECK_MV8_CANDIDATE_DIR(startx,starty+iDiamondSize,8);                                  CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1141    
1142                          /* now we're doing diagonal checks near our candidate */                          /* now we're doing diagonal checks near our candidate */
1143    
# Line 912  Line 1145 
1145                          {                          {
1146                                  bDirection = iDirection;                                  bDirection = iDirection;
1147                                  iDirection = 0;                                  iDirection = 0;
1148                                  startx=currMV->x; starty=currMV->y;                                  start_x = currMV->x;
1149                                    start_y = currMV->y;
1150                                  if (bDirection & 3) //our candidate is left or right                                  if (bDirection & 3) //our candidate is left or right
1151                                  {                                  {
1152                                          CHECK_MV8_CANDIDATE_DIR(startx,starty+iDiamondSize, 8);                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1153                                          CHECK_MV8_CANDIDATE_DIR(startx,starty-iDiamondSize, 4);                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1154                                  }                                  } else                  // what remains here is up or down
                                 else // what remains here is up or down  
1155                                  {                                  {
1156                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty, 2);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1157                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty, 1);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1158                                  }                                  }
1159    
1160                                  if (iDirection)                                  if (iDirection) {
1161                                  {       bDirection+=iDirection;                                          bDirection += iDirection;
1162                                          startx=currMV->x; starty=currMV->y;                                          start_x = currMV->x;
1163                                            start_y = currMV->y;
1164                                  }                                  }
1165                          }                          } else                          //about to quit, eh? not so fast....
                         else //about to quit, eh? not so fast....  
                         {  
                                 switch (bDirection)  
1166                                  {                                  {
1167                                    switch (bDirection) {
1168                                  case 2:                                  case 2:
1169                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1170                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                          start_y - iDiamondSize, 2 + 4);
1171                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1172                                                                                            start_y + iDiamondSize, 2 + 8);
1173                                          break;                                          break;
1174                                  case 1:                                  case 1:
1175                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1176                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                          start_y - iDiamondSize, 1 + 4);
1177                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1178                                                                                            start_y + iDiamondSize, 1 + 8);
1179                                          break;                                          break;
1180                                  case 2+4:                                  case 2+4:
1181                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1182                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                                                                          start_y - iDiamondSize, 1 + 4);
1183                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1184                                                                                            start_y - iDiamondSize, 2 + 4);
1185                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1186                                                                                            start_y + iDiamondSize, 2 + 8);
1187                                          break;                                          break;
1188                                  case 4:                                  case 4:
1189                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1190                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                                                                          start_y - iDiamondSize, 2 + 4);
1191                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1192                                                                                            start_y - iDiamondSize, 1 + 4);
1193                                          break;                                          break;
1194                                  case 8:                                  case 8:
1195                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1196                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                          start_y + iDiamondSize, 2 + 8);
1197                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1198                                                                                            start_y + iDiamondSize, 1 + 8);
1199                                          break;                                          break;
1200                                  case 1+4:                                  case 1+4:
1201                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1202                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                                                                          start_y + iDiamondSize, 1 + 8);
1203                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1204                                                                                            start_y - iDiamondSize, 1 + 4);
1205                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1206                                                                                            start_y - iDiamondSize, 2 + 4);
1207                                          break;                                          break;
1208                                  case 2+8:                                  case 2+8:
1209                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1210                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                          start_y - iDiamondSize, 1 + 4);
1211                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1212                                                                                            start_y + iDiamondSize, 1 + 8);
1213                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1214                                                                                            start_y + iDiamondSize, 2 + 8);
1215                                          break;                                          break;
1216                                  case 1+8:                                  case 1+8:
1217                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1218                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                          start_y - iDiamondSize, 2 + 4);
1219                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1220                                                                                            start_y + iDiamondSize, 2 + 8);
1221                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1222                                                                                            start_y + iDiamondSize, 1 + 8);
1223                                          break;                                          break;
1224                                  default: //1+2+4+8 == we didn't find anything at all                                  default: //1+2+4+8 == we didn't find anything at all
1225                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1226                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                          start_y - iDiamondSize, 1 + 4);
1227                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1228                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                          start_y + iDiamondSize, 1 + 8);
1229                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1230                                                                                            start_y - iDiamondSize, 2 + 4);
1231                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1232                                                                                            start_y + iDiamondSize, 2 + 8);
1233                                          break;                                          break;
1234                                  }                                  }
1235                                  if (!(iDirection)) break; //ok, the end. really                                  if (!(iDirection))
1236                                  else                                          break;          //ok, the end. really
1237                                  {       bDirection=iDirection;                                  else {
1238                                          startx=currMV->x; starty=currMV->y;                                          bDirection = iDirection;
1239                                            start_x = currMV->x;
1240                                            start_y = currMV->y;
1241                                  }                                  }
1242                          }                          }
1243                  }                  }
# Line 989  Line 1247 
1247  }  }
1248    
1249    
1250  int32_t Full8_MainSearch(  int32_t
1251                                          const uint8_t * const pRef,  Full8_MainSearch(const uint8_t * const pRef,
1252                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1253                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1254                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1255                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1256                                          const int x, const int y,                                   const int x,
1257                                          int32_t startx, int32_t starty,                                   const int y,
1258                                          int32_t iMinSAD,                             const int start_x,
1259                               const int start_y,
1260                               int iMinSAD,
1261                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1262                                          const VECTOR * const pmv,                             const int center_x,
1263                                          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1264                                          const int32_t min_dy, const int32_t max_dy,                                   const int32_t min_dx,
1265                                     const int32_t max_dx,
1266                                     const int32_t min_dy,
1267                                     const int32_t max_dy,
1268                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
1269                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
1270                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 1011  Line 1274 
1274          int32_t iSAD;          int32_t iSAD;
1275          int32_t dx,dy;          int32_t dx,dy;
1276          VECTOR backupMV;          VECTOR backupMV;
1277          backupMV.x = startx;  
1278          backupMV.y = starty;          backupMV.x = start_x;
1279            backupMV.y = start_y;
1280    
1281          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
1282                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 1021  Line 1285 
1285          return iMinSAD;          return iMinSAD;
1286  }  }
1287    
1288    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1289    
1290    int32_t
1291  int32_t Halfpel16_Refine(  Halfpel16_Refine(const uint8_t * const pRef,
         const uint8_t * const pRef,  
1292          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1293          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1294          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1295          const uint8_t * const cur,          const uint8_t * const cur,
1296          const int x, const int y,                                   const int x,
1297                                     const int y,
1298          VECTOR * const currMV,          VECTOR * const currMV,
1299          int32_t iMinSAD,          int32_t iMinSAD,
1300          const VECTOR * const pmv,                             const int center_x,
1301          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1302          const int32_t min_dy, const int32_t max_dy,                                   const int32_t min_dx,
1303                                     const int32_t max_dx,
1304                                     const int32_t min_dy,
1305                                     const int32_t max_dy,
1306          const int32_t iFcode,          const int32_t iFcode,
1307          const int32_t iQuant,          const int32_t iQuant,
1308          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1059  Line 1327 
1327  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1328    
1329    
1330  int32_t PMVfastSearch16(  
1331                                          const uint8_t * const pRef,  int32_t
1332    PMVfastSearch16(const uint8_t * const pRef,
1333                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1334                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1335                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1336                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1337                                          const int x, const int y,                                  const int x,
1338                                    const int y,
1339                                    const int start_x,      /* start is searched first, so it should contain the most */
1340                                    const int start_y,  /* likely motion vector for this block */
1341                                    const int center_x,     /* center is from where length of MVs is measured */
1342                                    const int center_y,
1343                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1344                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1345                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1099  Line 1373 
1373    
1374          MainSearch16FuncPtr MainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
1375    
 //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
1376          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1377    
1378          static int32_t threshA,threshB;          int32_t threshA, threshB;
1379          int32_t bPredEq;          int32_t bPredEq;
1380          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1381    
1382  /* Get maximum range */  /* Get maximum range */
1383          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,
1384                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1385    
1386  /* 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 */
1387    
1388          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1389          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1390          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1391          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1392          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1393          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1394    
1395          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1396            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1397    
1398          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1399                  threshA =  512;                  threshA =  512;
1400                  threshB = 1024;                  threshB = 1024;
1401            } else {
         }  
         else  
         {  
1402                  threshA = psad[0];                  threshA = psad[0];
1403                  threshB = threshA+256;                  threshB = threshA+256;
1404                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1405                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1406                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1407                            threshA = 1024;
1408                    if (threshB > 1792)
1409                            threshB = 1792;
1410          }          }
1411    
1412          iFound=0;          iFound=0;
# Line 1146  Line 1418 
1418     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1419  */  */
1420    
1421          *currMV=pmv[0];         /* current best := prediction */          currMV->x = start_x;
1422          if (!(MotionFlags & PMV_HALFPEL16 ))          currMV->y = start_y;
1423          {       /* This should NOT be necessary! */  
1424            if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
1425                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1426                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1427          }          }
1428    
1429          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1430                  currMV->x=max_dx;                  currMV->x=max_dx;
1431          }          }
1432          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1433                  currMV->x=min_dx;                  currMV->x=min_dx;
1434          }          }
1435          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1436                  currMV->y=max_dy;                  currMV->y=max_dy;
1437          }          }
1438          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1439                  currMV->y=min_dy;                  currMV->y=min_dy;
1440          }          }
1441    
1442          iMinSAD = sad16( cur,          iMinSAD =
1443                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1444                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1445          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1446            iMinSAD +=
1447          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1448          {                                            (uint8_t) iFcode, iQuant);
1449                  if (iMinSAD < 2*iQuant) // high chances for SKIP-mode  
1450                  {          if ((iMinSAD < 256) ||
1451                          if (!MVzero(*currMV))                  ((MVequal(*currMV, prevMB->mvs[0])) &&
1452                     ((int32_t) iMinSAD < prevMB->sad16))) {
1453                    if (iMinSAD < (int)(2 * iQuant))        // high chances for SKIP-mode
1454                          {                          {
1455                            if (!MVzero(*currMV)) {
1456                                  iMinSAD += MV16_00_BIAS;                                  iMinSAD += MV16_00_BIAS;
1457                                  CHECK_MV16_ZERO;                // (0,0) saves space for letterboxed pictures                                  CHECK_MV16_ZERO;                // (0,0) saves space for letterboxed pictures
1458                                  iMinSAD -= MV16_00_BIAS;                                  iMinSAD -= MV16_00_BIAS;
# Line 1236  Line 1508 
1508    
1509          if (!MVzero(pmv[1]))          if (!MVzero(pmv[1]))
1510          if (!MVequal(pmv[1],prevMB->mvs[0]))          if (!MVequal(pmv[1],prevMB->mvs[0]))
1511          if (!MVequal(pmv[1],pmv[0]))                          if (!MVequal(pmv[1], pmv[0])) {
1512          {                                  if (!(MotionFlags & PMV_HALFPEL16)) {
1513                  if (!(MotionFlags & PMV_HALFPEL16 ))                                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
1514                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
1515                  }                  }
1516    
1517                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1518          }          }
   
1519  // top neighbour, if allowed  // top neighbour, if allowed
1520          if (!MVzero(pmv[2]))          if (!MVzero(pmv[2]))
1521          if (!MVequal(pmv[2],prevMB->mvs[0]))          if (!MVequal(pmv[2],prevMB->mvs[0]))
1522          if (!MVequal(pmv[2],pmv[0]))          if (!MVequal(pmv[2],pmv[0]))
1523          if (!MVequal(pmv[2],pmv[1]))                                  if (!MVequal(pmv[2], pmv[1])) {
1524          {                                          if (!(MotionFlags & PMV_HALFPEL16)) {
1525                  if (!(MotionFlags & PMV_HALFPEL16 ))                                                  pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
1526                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
1527                  }                  }
1528                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
# Line 1263  Line 1532 
1532                  if (!MVequal(pmv[3],prevMB->mvs[0]))                  if (!MVequal(pmv[3],prevMB->mvs[0]))
1533                  if (!MVequal(pmv[3],pmv[0]))                  if (!MVequal(pmv[3],pmv[0]))
1534                  if (!MVequal(pmv[3],pmv[1]))                  if (!MVequal(pmv[3],pmv[1]))
1535                  if (!MVequal(pmv[3],pmv[2]))                                                                          if (!MVequal(pmv[3], pmv[2])) {
1536                  {                                                                                  if (!(MotionFlags & PMV_HALFPEL16)) {
1537                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                                                          pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
1538                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
1539                          }                          }
1540                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1541                                                                                                                             pmv[3].y);
1542                  }                  }
1543          }          }
1544    
1545          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )          if ((MVzero(*currMV)) &&
1546                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1547                  iMinSAD -= MV16_00_BIAS;                  iMinSAD -= MV16_00_BIAS;
1548    
1549    
# Line 1281  Line 1551 
1551     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.
1552  */  */
1553    
1554          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1555          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1556                     ((int32_t) iMinSAD < prevMB->sad16))) {
1557                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1558                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1559                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1302  Line 1573 
1573    
1574          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
1575                  MainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
1576          else          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
                 if (MotionFlags & PMV_ADVANCEDDIAMOND16)  
1577                          MainSearchPtr = AdvDiamond16_MainSearch;                          MainSearchPtr = AdvDiamond16_MainSearch;
1578                  else                  else
1579                          MainSearchPtr = Diamond16_MainSearch;                          MainSearchPtr = Diamond16_MainSearch;
1580    
1581          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1582    
1583    
1584  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1585          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1586                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1587                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1588                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1589                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1590                                                      iQuant, iFound);
1591    
1592          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1593                  *currMV = newMV;                  *currMV = newMV;
1594                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1595          }          }
1596    
1597          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1598  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1599    
1600                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1601                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1602                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1603                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1604                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1605                                                                      iDiamondSize, iFcode, iQuant, iFound);
1606    
1607                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1608                          *currMV = newMV;                          *currMV = newMV;
1609                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1610                  }                  }
1611                  }                  }
1612    
1613                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1614                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1615                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1616                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1617                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1618                                                                      iEdgedWidth, iDiamondSize, iFcode,
1619                                                                      iQuant, iFound);
1620    
1621                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1622                          *currMV = newMV;                          *currMV = newMV;
1623                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1624                  }                  }
# Line 1359  Line 1631 
1631    
1632  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1633          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1634                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1635                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1636                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1637                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1638    
1639  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1640          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1641          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1642          return iMinSAD;          return iMinSAD;
1643  }  }
1644    
# Line 1375  Line 1647 
1647    
1648    
1649    
1650  int32_t Diamond8_MainSearch(  int32_t
1651          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1652          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1653          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1654          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1655          const uint8_t * const cur,          const uint8_t * const cur,
1656          const int x, const int y,                                          const int x,
1657          int32_t startx, int32_t starty,                                          const int y,
1658                                            const int32_t start_x,
1659                                            const int32_t start_y,
1660          int32_t iMinSAD,          int32_t iMinSAD,
1661          VECTOR * const currMV,          VECTOR * const currMV,
1662          const VECTOR * const pmv,                                          const int center_x,
1663          const int32_t min_dx, const int32_t max_dx,                                          const int center_y,
1664          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1665                                            const int32_t max_dx,
1666                                            const int32_t min_dy,
1667                                            const int32_t max_dy,
1668          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1669          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1670          const int32_t iFcode,          const int32_t iFcode,
# Line 1397  Line 1674 
1674  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1675    
1676          int32_t iDirection=0;          int32_t iDirection=0;
1677            int32_t iDirectionBackup;
1678          int32_t iSAD;          int32_t iSAD;
1679          VECTOR backupMV;          VECTOR backupMV;
1680          backupMV.x = startx;  
1681          backupMV.y = starty;          backupMV.x = start_x;
1682            backupMV.y = start_y;
1683    
1684  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1685    
# Line 1409  Line 1688 
1688          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1689          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1690    
1691          if (iDirection)          if (iDirection) {
1692                  while (!iFound)                  while (!iFound) {
                 {  
1693                          iFound = 1;                          iFound = 1;
1694                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1695                            iDirectionBackup = iDirection;
1696    
1697                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1698                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1699                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1700                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1701                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1702                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1703                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1704                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1705                                                                                      backupMV.y - iDiamondSize, 3);
1706                            if (iDirectionBackup != 3)
1707                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1708                                                                                      backupMV.y + iDiamondSize, 4);
1709                    }
1710            } else {
1711                    currMV->x = start_x;
1712                    currMV->y = start_y;
1713                  }                  }
1714          else          return iMinSAD;
1715    }
1716    
1717    
1718    
1719    
1720    int32_t
1721    Square8_MainSearch(const uint8_t * const pRef,
1722                                       const uint8_t * const pRefH,
1723                                       const uint8_t * const pRefV,
1724                                       const uint8_t * const pRefHV,
1725                                       const uint8_t * const cur,
1726                                       const int x,
1727                                       const int y,
1728                                       const int32_t start_x,
1729                                       const int32_t start_y,
1730                                       int32_t iMinSAD,
1731                                       VECTOR * const currMV,
1732                                       const int center_x,
1733                                       const int center_y,
1734                                       const int32_t min_dx,
1735                                       const int32_t max_dx,
1736                                       const int32_t min_dy,
1737                                       const int32_t max_dy,
1738                                       const int32_t iEdgedWidth,
1739                                       const int32_t iDiamondSize,
1740                                       const int32_t iFcode,
1741                                       const int32_t iQuant,
1742                                       int iFound)
1743          {          {
1744                  currMV->x = startx;  /* Do a square search around given starting point, return SAD of best */
1745                  currMV->y = starty;  
1746            int32_t iDirection = 0;
1747            int32_t iSAD;
1748            VECTOR backupMV;
1749    
1750            backupMV.x = start_x;
1751            backupMV.y = start_y;
1752    
1753    /* It's one search with full square pattern, and new parts for all following diamonds */
1754    
1755    /*   new direction are extra, so 1-4 is normal diamond
1756          537
1757          1*2
1758          648
1759    */
1760    
1761            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1762            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1763            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1764            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1765    
1766            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1767                                                             backupMV.y - iDiamondSize, 5);
1768            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1769                                                             backupMV.y + iDiamondSize, 6);
1770            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1771                                                             backupMV.y - iDiamondSize, 7);
1772            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1773                                                             backupMV.y + iDiamondSize, 8);
1774    
1775    
1776            if (iDirection) {
1777                    while (!iFound) {
1778                            iFound = 1;
1779                            backupMV = *currMV;
1780    
1781                            switch (iDirection) {
1782                            case 1:
1783                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1784                                                                                       backupMV.y, 1);
1785                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1786                                                                                     backupMV.y - iDiamondSize, 5);
1787                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1788                                                                                     backupMV.y - iDiamondSize, 7);
1789                                    break;
1790                            case 2:
1791                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1792                                                                                     2);
1793                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1794                                                                                     backupMV.y + iDiamondSize, 6);
1795                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1796                                                                                     backupMV.y + iDiamondSize, 8);
1797                                    break;
1798    
1799                            case 3:
1800                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1801                                                                                     4);
1802                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1803                                                                                     backupMV.y - iDiamondSize, 7);
1804                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1805                                                                                     backupMV.y + iDiamondSize, 8);
1806                                    break;
1807    
1808                            case 4:
1809                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1810                                                                                     3);
1811                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1812                                                                                     backupMV.y - iDiamondSize, 5);
1813                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1814                                                                                     backupMV.y + iDiamondSize, 6);
1815                                    break;
1816    
1817                            case 5:
1818                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1819                                                                                     1);
1820                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1821                                                                                     3);
1822                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1823                                                                                     backupMV.y - iDiamondSize, 5);
1824                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1825                                                                                     backupMV.y + iDiamondSize, 6);
1826                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1827                                                                                     backupMV.y - iDiamondSize, 7);
1828                                    break;
1829    
1830                            case 6:
1831                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1832                                                                                     2);
1833                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1834                                                                                     3);
1835    
1836                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1837                                                                                     backupMV.y - iDiamondSize, 5);
1838                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1839                                                                                     backupMV.y + iDiamondSize, 6);
1840                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1841                                                                                     backupMV.y + iDiamondSize, 8);
1842    
1843                                    break;
1844    
1845                            case 7:
1846                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1847                                                                                       backupMV.y, 1);
1848                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1849                                                                                     4);
1850                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1851                                                                                     backupMV.y - iDiamondSize, 5);
1852                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1853                                                                                     backupMV.y - iDiamondSize, 7);
1854                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1855                                                                                     backupMV.y + iDiamondSize, 8);
1856                                    break;
1857    
1858                            case 8:
1859                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1860                                                                                     2);
1861                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1862                                                                                     4);
1863                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1864                                                                                     backupMV.y + iDiamondSize, 6);
1865                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1866                                                                                     backupMV.y - iDiamondSize, 7);
1867                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1868                                                                                     backupMV.y + iDiamondSize, 8);
1869                                    break;
1870                            default:
1871                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1872                                                                                     1);
1873                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1874                                                                                     2);
1875                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1876                                                                                     3);
1877                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1878                                                                                     4);
1879    
1880                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1881                                                                                     backupMV.y - iDiamondSize, 5);
1882                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1883                                                                                     backupMV.y + iDiamondSize, 6);
1884                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1885                                                                                     backupMV.y - iDiamondSize, 7);
1886                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1887                                                                                     backupMV.y + iDiamondSize, 8);
1888                                    break;
1889                            }
1890                    }
1891            } else {
1892                    currMV->x = start_x;
1893                    currMV->y = start_y;
1894          }          }
1895          return iMinSAD;          return iMinSAD;
1896  }  }
1897    
1898  int32_t Halfpel8_Refine(  
1899          const uint8_t * const pRef,  
1900    
1901    
1902    int32_t
1903    Halfpel8_Refine_c(const uint8_t * const pRef,
1904          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1905          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1906          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1907          const uint8_t * const cur,          const uint8_t * const cur,
1908          const int x, const int y,                                    const int x,
1909                                      const int y,
1910          VECTOR * const currMV,          VECTOR * const currMV,
1911          int32_t iMinSAD,          int32_t iMinSAD,
1912          const VECTOR * const pmv,                                    const int center_x,
1913          const int32_t min_dx, const int32_t max_dx,                                    const int center_y,
1914          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
1915                                      const int32_t max_dx,
1916                                      const int32_t min_dy,
1917                                      const int32_t max_dy,
1918          const int32_t iFcode,          const int32_t iFcode,
1919          const int32_t iQuant,          const int32_t iQuant,
1920          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1468  Line 1939 
1939    
1940  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1941    
1942  int32_t PMVfastSearch8(  int32_t
1943                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1944                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1945                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1946                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1947                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1948                                          const int x, const int y,                             const int x,
1949                                          const int start_x, const int start_y,                             const int y,
1950                               const int start_x,
1951                               const int start_y,
1952                                    const int center_x,
1953                                    const int center_y,
1954                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1955                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1956                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1508  Line 1983 
1983  //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1984          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1985    
1986          static int32_t threshA,threshB;           int32_t threshA, threshB;
1987          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1988          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1989    
# Line 1521  Line 1996 
1996          startMV.y = start_y;          startMV.y = start_y;
1997    
1998          /* Get maximum range */          /* Get maximum range */
1999          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,
2000                    x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2001    
2002          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
2003          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2004            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2005            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2006            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2007          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
2008    
2009          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
2010            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
2011    
2012          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2013                  threshA =  512/4;                  threshA =  512/4;
2014                  threshB = 1024/4;                  threshB = 1024 / 4;
2015    
2016          }          } else {
2017          else                  threshA = psad[0] / 4;  /* good estimate? */
         {  
                 threshA = psad[0]/4;                    /* good estimate */  
2018                  threshB = threshA+256/4;                  threshB = threshA+256/4;
2019                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
2020                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
2021                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
2022                            threshA = 1024 / 4;
2023                    if (threshB > 1792 / 4)
2024                            threshB = 1792 / 4;
2025          }          }
2026    
2027          iFound=0;          iFound=0;
# Line 1561  Line 2036 
2036    
2037  // Prepare for main loop  // Prepare for main loop
2038    
2039  //      if (MotionFlags & PMV_USESQUARES8)    if (MotionFlags & PMV_USESQUARES8)
2040  //              MainSearchPtr = Square8_MainSearch;        MainSearchPtr = Square8_MainSearch;
2041  //      else    else
2042    
2043          if (MotionFlags & PMV_ADVANCEDDIAMOND8)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2044                  MainSearchPtr = AdvDiamond8_MainSearch;                  MainSearchPtr = AdvDiamond8_MainSearch;
# Line 1573  Line 2048 
2048    
2049          *currMV = startMV;          *currMV = startMV;
2050    
2051          iMinSAD = sad8( cur,          iMinSAD =
2052                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2053                          iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2054          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode, iQuant);                                                  iEdgedWidth), iEdgedWidth);
2055            iMinSAD +=
2056                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2057                                             (uint8_t) iFcode, iQuant);
2058    
2059          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))
2060                                  && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )                                                                  && ((int32_t) iMinSAD <
2061          {                                                                          prevMB->sad8[iSubBlock]))) {
2062                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2063                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2064                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1618  Line 2096 
2096  // the median prediction might be even better than mv16  // the median prediction might be even better than mv16
2097    
2098          if (!MVequal(pmv[0],startMV))          if (!MVequal(pmv[0],startMV))
2099                  CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);                  CHECK_MV8_CANDIDATE(center_x, center_y);
2100    
2101  // (0,0) if needed  // (0,0) if needed
2102          if (!MVzero(pmv[0]))          if (!MVzero(pmv[0]))
# Line 1629  Line 2107 
2107          if (!MVzero(prevMB->mvs[iSubBlock]))          if (!MVzero(prevMB->mvs[iSubBlock]))
2108          if (!MVequal(prevMB->mvs[iSubBlock],startMV))          if (!MVequal(prevMB->mvs[iSubBlock],startMV))
2109          if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))          if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))
2110          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);                                  CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
2111                                                                            prevMB->mvs[iSubBlock].y);
2112    
2113          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2114          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2115                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2116                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2117                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2118                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
2119                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
2120          }          }
2121    
   
2122  // left neighbour, if allowed and needed  // left neighbour, if allowed and needed
2123          if (!MVzero(pmv[1]))          if (!MVzero(pmv[1]))
2124          if (!MVequal(pmv[1],startMV))          if (!MVequal(pmv[1],startMV))
2125          if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))          if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))
2126          if (!MVequal(pmv[1],pmv[0]))                                  if (!MVequal(pmv[1], pmv[0])) {
2127          {                                          if (!(MotionFlags & PMV_HALFPEL8)) {
2128                  if (!(MotionFlags & PMV_HALFPEL8 ))                                                  pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2129                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2130                  }                  }
2131                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2132          }          }
   
2133  // top neighbour, if allowed and needed  // top neighbour, if allowed and needed
2134          if (!MVzero(pmv[2]))          if (!MVzero(pmv[2]))
2135          if (!MVequal(pmv[2],startMV))          if (!MVequal(pmv[2],startMV))
2136          if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))          if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))
2137          if (!MVequal(pmv[2],pmv[0]))          if (!MVequal(pmv[2],pmv[0]))
2138          if (!MVequal(pmv[2],pmv[1]))                                          if (!MVequal(pmv[2], pmv[1])) {
2139          {                                                  if (!(MotionFlags & PMV_HALFPEL8)) {
2140                  if (!(MotionFlags & PMV_HALFPEL8 ))                                                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2141                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2142                  }                  }
2143                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
# Line 1672  Line 2148 
2148          if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))          if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))
2149          if (!MVequal(pmv[3],pmv[0]))          if (!MVequal(pmv[3],pmv[0]))
2150          if (!MVequal(pmv[3],pmv[1]))          if (!MVequal(pmv[3],pmv[1]))
2151          if (!MVequal(pmv[3],pmv[2]))                                                                                          if (!MVequal(pmv[3], pmv[2])) {
2152                  {                                                                                                  if (!
2153                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                                                          (MotionFlags &
2154                          {       pmv[3].x = EVEN(pmv[3].x);                                                                                                           PMV_HALFPEL8)) {
2155                                                                                                            pmv[3].x = EVEN(pmv[3].x);
2156                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2157                          }                          }
2158                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
2159                                                                                                                                            pmv[3].y);
2160                  }                  }
2161          }          }
2162    
2163          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )          if ((MVzero(*currMV)) &&
2164                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2165                  iMinSAD -= MV8_00_BIAS;                  iMinSAD -= MV8_00_BIAS;
2166    
2167    
# Line 1690  Line 2169 
2169     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.
2170  */  */
2171    
2172          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2173          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2174                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2175                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2176                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2177                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1711  Line 2191 
2191          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2192    
2193  /* 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 */
2194          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2195                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2196                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2197                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2198                                                      iQuant, iFound);
2199    
2200          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2201                  *currMV = newMV;                  *currMV = newMV;
2202                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2203          }          }
2204    
2205          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2206  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
2207    
2208                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2209                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2210                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2211                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2212                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2213                                                                      iDiamondSize, iFcode, iQuant, iFound);
2214    
2215                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2216                          *currMV = newMV;                          *currMV = newMV;
2217                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2218                  }                  }
2219                  }                  }
2220    
2221                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2222                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2223                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2224                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2225                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2226                                                                      iQuant, iFound);
2227    
2228                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2229                          *currMV = newMV;                          *currMV = newMV;
2230                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2231                  }                  }
# Line 1759  Line 2238 
2238    
2239  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
2240          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2241                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2242                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2243                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2244                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2245    
2246    
2247  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
2248          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2249          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2250    
2251          return iMinSAD;          return iMinSAD;
2252  }  }
2253    
2254  int32_t EPZSSearch16(  int32_t
2255                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2256                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2257                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2258                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2259                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2260                                          const int x, const int y,                           const int x,
2261                             const int y,
2262                            const int start_x,
2263                            const int start_y,
2264                            const int center_x,
2265                            const int center_y,
2266                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2267                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2268                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1809  Line 2293 
2293          int32_t psad[8];          int32_t psad[8];
2294    
2295          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2296    
2297  //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2298          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
2299          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
2300    
2301          static int32_t thresh2;           int32_t thresh2;
2302          int32_t bPredEq;          int32_t bPredEq;
2303          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2304    
2305          MainSearch16FuncPtr MainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2306    
2307          if (oldMBs == NULL)          if (oldMBs == NULL) {
2308          {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2309  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2310          }          }
2311          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2312    
2313  /* Get maximum range */  /* Get maximum range */
2314          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,
2315                          x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
2316    
2317          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
2318          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2319            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2320            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2321            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2322          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2323            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2324          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2325    
2326  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2327          MinSAD=SAD          MinSAD=SAD
# Line 1847  Line 2332 
2332    
2333  // Prepare for main loop  // Prepare for main loop
2334    
2335          *currMV=pmv[0];         /* current best := median prediction */          currMV->x = start_x;
2336          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2337          {  
2338            if (!(MotionFlags & PMV_HALFPEL16)) {
2339                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2340                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2341          }          }
# Line 1865  Line 2351 
2351    
2352  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2353    
2354          iMinSAD = sad16( cur,          iMinSAD =
2355                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2356                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2357          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2358            iMinSAD +=
2359                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2360                                              (uint8_t) iFcode, iQuant);
2361    
2362  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2363          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD < 256) ||
2364                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2365                     ((int32_t) iMinSAD < prevMB->sad16))) {
2366                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2367                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2368                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1887  Line 2377 
2377  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2378  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
2379    
2380          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2381                  thresh2 =  512;                  thresh2 =  512;
2382          }          } else {
         else  
         {  
2383  /* 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] */
2384    
2385                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1904  Line 2391 
2391    
2392    
2393  // left neighbour, if allowed  // left neighbour, if allowed
2394          if (x != 0)          if (x != 0) {
2395          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2396                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2397                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2398                  }                  }
2399                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2400          }          }
   
2401  // top neighbour, if allowed  // top neighbour, if allowed
2402          if (y != 0)          if (y != 0) {
2403          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2404                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2405                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2406                  }                  }
2407                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
2408    
2409  // top right neighbour, if allowed  // top right neighbour, if allowed
2410                  if ((uint32_t)x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
2411                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2412                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2413                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2414                          }                          }
2415                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1938  Line 2421 
2421  */  */
2422    
2423          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2424                  || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2425                  {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2426                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2427                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2428                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1960  Line 2443 
2443    
2444  // top neighbour  // top neighbour
2445          if (y != 0)          if (y != 0)
2446                  CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2447                                                             (prevMB - iWcount)->mvs[0].y);
2448    
2449  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2450    
# Line 1969  Line 2453 
2453    
2454  // bottom neighbour, dito  // bottom neighbour, dito
2455          if ((uint32_t)y != iHcount-1)          if ((uint32_t)y != iHcount-1)
2456                  CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2457                                                             (prevMB + iWcount)->mvs[0].y);
2458    
2459  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2460          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2) {
                 {  
2461                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2462                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2463                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1984  Line 2468 
2468    
2469          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2470    
2471          if (MotionFlags & PMV_USESQUARES8)          if (MotionFlags & PMV_USESQUARES16)
2472                  MainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
2473          else          else
2474             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
         if (MotionFlags & PMV_ADVANCEDDIAMOND8)  
2475                  MainSearchPtr = AdvDiamond16_MainSearch;                  MainSearchPtr = AdvDiamond16_MainSearch;
2476          else          else
2477                  MainSearchPtr = Diamond16_MainSearch;                  MainSearchPtr = Diamond16_MainSearch;
2478    
2479  /* 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 */
2480    
2481          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2482                          x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2483                          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,
2484                          2, iFcode, iQuant, 0);                                                    min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2485    
2486          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2487                  *currMV = newMV;                  *currMV = newMV;
2488                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2489          }          }
2490    
2491    
2492          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
2493  /* 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) */
2494    
2495                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2496                  {                          iSAD =
2497                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2498                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2499                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2500                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2501                  }                  }
2502    
2503                  if (iSAD < iMinSAD)                  if (iSAD < iMinSAD) {
                 {  
2504                          *currMV = newMV;                          *currMV = newMV;
2505                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2506                  }                  }
2507    
2508                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2509                  {                          iSAD =
2510                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2511                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2512                          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);  
2513    
2514                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2515                                  *currMV = newMV;                                  *currMV = newMV;
2516                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2517                          }                          }
# Line 2044  Line 2522 
2522    
2523  EPZS16_Terminate_with_Refine:  EPZS16_Terminate_with_Refine:
2524          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
2525                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2526                                  x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2527                                  currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2528                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
2529    
2530  EPZS16_Terminate_without_Refine:  EPZS16_Terminate_without_Refine:
2531    
2532          *oldMB = *prevMB;          *oldMB = *prevMB;
2533    
2534          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2535          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2536          return iMinSAD;          return iMinSAD;
2537  }  }
2538    
2539    
2540  int32_t EPZSSearch8(  int32_t
2541                                          const uint8_t * const pRef,  EPZSSearch8(const uint8_t * const pRef,
2542                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2543                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2544                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2545                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2546                                          const int x, const int y,                          const int x,
2547                                          const int start_x, const int start_y,                          const int y,
2548                            const int start_x,
2549                            const int start_y,
2550                            const int center_x,
2551                            const int center_y,
2552                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2553                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2554                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 2109  Line 2591 
2591          MainSearch8FuncPtr MainSearchPtr;          MainSearch8FuncPtr MainSearchPtr;
2592    
2593  /* Get maximum range */  /* Get maximum range */
2594          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,
2595                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2596    
2597  /* 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 */
2598    
2599          if (!(MotionFlags & PMV_HALFPEL8 ))          if (!(MotionFlags & PMV_HALFPEL8)) {
2600          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2601            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2602            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2603            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2604          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2605            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2606          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);
2607    
2608    
2609  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 2134  Line 2616 
2616  // Prepare for main loop  // Prepare for main loop
2617    
2618    
2619          if (!(MotionFlags & PMV_HALFPEL8))          if (!(MotionFlags & PMV_HALFPEL8)) {
         {  
2620                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2621                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2622          }          }
# Line 2152  Line 2633 
2633  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2634    
2635    
2636          iMinSAD = sad8( cur,          iMinSAD =
2637                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2638                  iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2639          iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                  iEdgedWidth), iEdgedWidth);
2640            iMinSAD +=
2641                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2642                                             (uint8_t) iFcode, iQuant);
2643    
2644    
2645  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2646          if (iMinSAD < 256/4 )          if (iMinSAD < 256 / 4) {
                 {  
2647                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2648                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2649                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 2177  Line 2660 
2660          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
2661    
2662  // left neighbour, if allowed  // left neighbour, if allowed
2663          if (psad[1] != MV_MAX_ERROR)          if (psad[1] != MV_MAX_ERROR) {
2664          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2665                  if (!(MotionFlags & PMV_HALFPEL8 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2666                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2667                  }                  }
2668                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2669          }          }
   
2670  // top neighbour, if allowed  // top neighbour, if allowed
2671          if (psad[2] != MV_MAX_ERROR)          if (psad[2] != MV_MAX_ERROR) {
2672          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2673                  if (!(MotionFlags & PMV_HALFPEL8 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2674                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2675                  }                  }
2676                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2677    
2678  // top right neighbour, if allowed  // top right neighbour, if allowed
2679                  if (psad[3] != MV_MAX_ERROR)                  if (psad[3] != MV_MAX_ERROR) {
2680                  {                          if (!(MotionFlags & PMV_HALFPEL8)) {
2681                          if (!(MotionFlags & PMV_HALFPEL8 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2682                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2683                          }                          }
2684                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 2217  Line 2696 
2696     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]
2697  */  */
2698    
2699          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
                 {  
2700                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2701                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2702                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 2236  Line 2714 
2714    
2715  // there is no EPZS^2 for inter4v at the moment  // there is no EPZS^2 for inter4v at the moment
2716    
2717  //      if (MotionFlags & PMV_USESQUARES8)    if (MotionFlags & PMV_USESQUARES8)
2718  //              MainSearchPtr = Square8_MainSearch;        MainSearchPtr = Square8_MainSearch;
2719  //      else    else
2720    
2721          if (MotionFlags & PMV_ADVANCEDDIAMOND8)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2722                  MainSearchPtr = AdvDiamond8_MainSearch;                  MainSearchPtr = AdvDiamond8_MainSearch;
2723          else          else
2724                  MainSearchPtr = Diamond8_MainSearch;                  MainSearchPtr = Diamond8_MainSearch;
2725    
2726          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2727                  x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2728                  currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2729                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2730                  iDiamondSize, iFcode, iQuant, 0);                                                    iQuant, 0);
2731    
2732    
2733          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2734                  *currMV = newMV;                  *currMV = newMV;
2735                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2736          }          }
2737    
2738          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2739  /* 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) */
2740    
2741                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2742                  {                          iSAD =
2743                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2744                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2745                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2746                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2747    
2748                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2749                                  *currMV = newMV;                                  *currMV = newMV;
2750                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2751                          }                          }
2752                  }                  }
2753    
2754                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2755                  {                          iSAD =
2756                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2757                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2758                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2759                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, 0);
2760    
2761                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2762                                  *currMV = newMV;                                  *currMV = newMV;
2763                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2764                          }                          }
# Line 2295  Line 2769 
2769    
2770  EPZS8_Terminate_with_Refine:  EPZS8_Terminate_with_Refine:
2771          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2772                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2773                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2774                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2775                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2776    
2777  EPZS8_Terminate_without_Refine:  EPZS8_Terminate_without_Refine:
2778    
2779          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2780          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2781          return iMinSAD;          return iMinSAD;
2782  }  }
2783    
2784    
2785    
2786    int32_t
2787    PMVfastIntSearch16(const uint8_t * const pRef,
2788                                    const uint8_t * const pRefH,
2789                                    const uint8_t * const pRefV,
2790                                    const uint8_t * const pRefHV,
2791                                    const IMAGE * const pCur,
2792                                    const int x,
2793                                    const int y,
2794                                    const int start_x,              /* start should be most likely vector */
2795                                    const int start_y,
2796                                    const int center_x,             /* center is from where length of MVs is measured */
2797                                    const int center_y,
2798                                    const uint32_t MotionFlags,
2799                                    const uint32_t iQuant,
2800                                    const uint32_t iFcode,
2801                                    const MBParam * const pParam,
2802                                    const MACROBLOCK * const pMBs,
2803                                    const MACROBLOCK * const prevMBs,
2804                                    VECTOR * const currMV,
2805                                    VECTOR * const currPMV)
2806    {
2807            const uint32_t iWcount = pParam->mb_width;
2808            const int32_t iWidth = pParam->width;
2809            const int32_t iHeight = pParam->height;
2810            const int32_t iEdgedWidth = pParam->edged_width;
2811    
2812            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2813            const VECTOR zeroMV = { 0, 0 };
2814    
2815            int32_t iDiamondSize;
2816    
2817            int32_t min_dx;
2818            int32_t max_dx;
2819            int32_t min_dy;
2820            int32_t max_dy;
2821    
2822            int32_t iFound;
2823    
2824  /* ***********************************************************          VECTOR newMV;
2825          bvop motion estimation          VECTOR backupMV;
 // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)  
 ***************************************************************/  
2826    
2827            VECTOR pmv[4];
2828            int32_t psad[4];
2829    
2830  void MotionEstimationBVOP(          MainSearch16FuncPtr MainSearchPtr;
                         MBParam * const pParam,  
                         FRAMEINFO * const frame,  
2831    
2832                          // forward (past) reference          MACROBLOCK *const prevMB = (MACROBLOCK *const)prevMBs + x + y * iWcount;
2833                          const MACROBLOCK * const f_mbs,          MACROBLOCK *const pMB = (MACROBLOCK *const)(pMBs + x + y * iWcount);
2834                      const IMAGE * const f_ref,  
2835                          const IMAGE * const f_refH,          int32_t threshA, threshB;
2836                      const IMAGE * const f_refV,          int32_t bPredEq;
2837                          const IMAGE * const f_refHV,          int32_t iMinSAD, iSAD;
2838                          // backward (future) reference  
2839                          const MACROBLOCK * const b_mbs,  
2840                      const IMAGE * const b_ref,  /* Get maximum range */
2841                          const IMAGE * const b_refH,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2842                      const IMAGE * const b_refV,                            iFcode);
2843                          const IMAGE * const b_refHV)  
2844  {  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2845      const uint32_t mb_width = pParam->mb_width;  
2846      const uint32_t mb_height = pParam->mb_height;          if ((x == 0) && (y == 0)) {
2847          const int32_t edged_width = pParam->edged_width;                  threshA = 512;
2848                    threshB = 1024;
2849          uint32_t i,j;  
2850                    bPredEq = 0;
2851          int32_t f_sad16;                  psad[0] = psad[1] = psad[2] = psad[3] = 0;
2852          int32_t b_sad16;                  *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2853          int32_t i_sad16;  
2854          int32_t d_sad16;          } else {
2855          int32_t best_sad;  
2856                    bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2857          VECTOR pmv_dontcare;  
2858                    threshA = psad[0];
2859          // note: i==horizontal, j==vertical                  threshB = threshA + 256;
2860      for (j = 0; j < mb_height; j++)                  if (threshA < 512)
2861          {                          threshA = 512;
2862                  for (i = 0; i < mb_width; i++)                  if (threshA > 1024)
2863                  {                          threshA = 1024;
2864                          MACROBLOCK *mb = &frame->mbs[i + j*mb_width];                  if (threshB > 1792)
2865                          const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];                          threshB = 1792;
2866                          const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];  
2867                    *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;  
2868                          }                          }
2869    
2870            iFound = 0;
2871    
2872    /* Step 4: Calculate SAD around the Median prediction.
2873       MinSAD=SAD
2874       If Motion Vector equal to Previous frame motion vector
2875       and MinSAD<PrevFrmSAD goto Step 10.
2876       If SAD<=256 goto Step 10.
2877    */
2878    
2879                          // forward search          if (currMV->x > max_dx) {
2880                          f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                  currMV->x = EVEN(max_dx);
2881                                                  &frame->image,          }
2882                                                  i, j,          if (currMV->x < min_dx) {
2883                                                  frame->motion_flags,  frame->quant, frame->fcode,                  currMV->x = EVEN(min_dx);
2884                                                  pParam,          }
2885                                                  f_mbs, f_mbs /* todo */,          if (currMV->y > max_dy) {
2886                                                  &mb->mvs[0], &pmv_dontcare);    // ignore pmv                  currMV->y = EVEN(max_dy);
2887            }
2888                          // backward search          if (currMV->y < min_dy) {
2889                          b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                  currMV->y = EVEN(min_dy);
2890                                                  &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;  
2891    
2892            iMinSAD =
2893                    sad16(cur,
2894                              get_iref_mv(pRef, x, y, 16, currMV,
2895                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2896            iMinSAD +=
2897                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2898                                              (uint8_t) iFcode, iQuant);
2899    
2900                          if (f_sad16 < b_sad16)          if ((iMinSAD < 256) ||
2901                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2902                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2903                    if (iMinSAD < (int)(2 * iQuant))        // high chances for SKIP-mode
2904                          {                          {
2905                                  best_sad = f_sad16;                          if (!MVzero(*currMV)) {
2906                                  mb->mode = MODE_FORWARD;                                  iMinSAD += MV16_00_BIAS;
2907                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2908                                    iMinSAD -= MV16_00_BIAS;
2909                            }
2910                          }                          }
2911    
2912                    if (MotionFlags & PMV_EARLYSTOP16)
2913                            goto PMVfastInt16_Terminate_with_Refine;
2914            }
2915    
2916    
2917    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2918       vector of the median.
2919       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2920    */
2921    
2922            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2923                    iFound = 2;
2924    
2925    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2926       Otherwise select large Diamond Search.
2927    */
2928    
2929            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2930                    iDiamondSize = 2;               // halfpel units!
2931                          else                          else
2932                          {                  iDiamondSize = 4;               // halfpel units!
2933                                  best_sad = b_sad16;  
2934                                  mb->mode = MODE_BACKWARD;  /*
2935       Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2936       Also calculate (0,0) but do not subtract offset.
2937       Let MinSAD be the smallest SAD up to this point.
2938       If MV is (0,0) subtract offset.
2939    */
2940    
2941    // (0,0) is often a good choice
2942    
2943            if (!MVzero(pmv[0]))
2944                    CHECK_MV16_ZERO;
2945    
2946    // previous frame MV is always possible
2947    
2948            if (!MVzero(prevMB->i_mvs[0]))
2949                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2950                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2951    
2952    // left neighbour, if allowed
2953    
2954            if (!MVzero(pmv[1]))
2955                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2956                            if (!MVequal(pmv[1], pmv[0]))
2957                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2958    
2959    // top neighbour, if allowed
2960            if (!MVzero(pmv[2]))
2961                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
2962                            if (!MVequal(pmv[2], pmv[0]))
2963                                    if (!MVequal(pmv[2], pmv[1]))
2964                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2965    
2966    // top right neighbour, if allowed
2967                                            if (!MVzero(pmv[3]))
2968                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
2969                                                            if (!MVequal(pmv[3], pmv[0]))
2970                                                                    if (!MVequal(pmv[3], pmv[1]))
2971                                                                            if (!MVequal(pmv[3], pmv[2]))
2972                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
2973                                                                                                                             pmv[3].y);
2974    
2975            if ((MVzero(*currMV)) &&
2976                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2977                    iMinSAD -= MV16_00_BIAS;
2978    
2979    
2980    /* Step 6: If MinSAD <= thresa goto Step 10.
2981       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2982    */
2983    
2984            if ((iMinSAD <= threshA) ||
2985                    (MVequal(*currMV, prevMB->i_mvs[0]) &&
2986                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2987    
2988                    if (MotionFlags & PMV_EARLYSTOP16)
2989                            goto PMVfastInt16_Terminate_with_Refine;
2990                          }                          }
2991    
2992                          if (i_sad16 < best_sad)  
2993                          {  /************ (Diamond Search)  **************/
2994                                  best_sad = i_sad16;  /*
2995                                  mb->mode = MODE_INTERPOLATE;     Step 7: Perform Diamond search, with either the small or large diamond.
2996       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
2997       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
2998       If center then goto step 10.
2999       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
3000       Refine by using small diamond and goto step 10.
3001    */
3002    
3003            if (MotionFlags & PMV_USESQUARES16)
3004                    MainSearchPtr = Square16_MainSearch;
3005            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
3006                    MainSearchPtr = AdvDiamond16_MainSearch;
3007            else
3008                    MainSearchPtr = Diamond16_MainSearch;
3009    
3010            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
3011    
3012    
3013    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
3014            iSAD =
3015                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
3016                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
3017                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
3018                                                      iQuant, iFound);
3019    
3020            if (iSAD < iMinSAD) {
3021                    *currMV = newMV;
3022                    iMinSAD = iSAD;
3023                          }                          }
3024    
3025                          if (d_sad16 < best_sad)          if (MotionFlags & PMV_EXTSEARCH16) {
3026                          {  /* extended: search (up to) two more times: orignal prediction and (0,0) */
3027                                  best_sad = d_sad16;  
3028                                  mb->mode = MODE_DIRECT;                  if (!(MVequal(pmv[0], backupMV))) {
3029                            iSAD =
3030                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
3031                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
3032                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
3033                                                                      iDiamondSize, iFcode, iQuant, iFound);
3034    
3035                            if (iSAD < iMinSAD) {
3036                                    *currMV = newMV;
3037                                    iMinSAD = iSAD;
3038                            }
3039                          }                          }
3040    
3041                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
3042                            iSAD =
3043                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
3044                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
3045                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
3046                                                                      iQuant, iFound);
3047    
3048                            if (iSAD < iMinSAD) {
3049                                    *currMV = newMV;
3050                                    iMinSAD = iSAD;
3051                            }
3052                  }                  }
3053          }          }
3054    
3055    /*
3056       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
3057    */
3058    
3059    PMVfastInt16_Terminate_with_Refine:
3060    
3061            pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
3062            pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
3063    
3064            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
3065                    iMinSAD =
3066                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
3067                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
3068                                                             iFcode, iQuant, iEdgedWidth);
3069    
3070            pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
3071    
3072            currPMV->x = currMV->x - center_x;
3073            currPMV->y = currMV->y - center_y;
3074            return iMinSAD;
3075  }  }
3076    

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

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