[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 195, Wed Jun 12 20:38:41 2002 UTC revision 476, Thu Sep 12 18:53:11 2002 UTC
# Line 1  Line 1 
1  /**************************************************************************  /*****************************************************************************
2   *   *
3   *  Modifications:   *  XVID MPEG-4 VIDEO CODEC
4     *  - Motion Estimation module -
5   *   *
6   *      01.05.2002      updated MotionEstimationBVOP   *  Copyright(C) 2002 Christoph Lampert <gruel@web.de>
7   *      25.04.2002 partial prevMB conversion   *  Copyright(C) 2002 Michael Militzer <michael@xvid.org>
8   *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>   *  Copyright(C) 2002 Edouard Gomez <ed.gomez@wanadoo.fr>
  *  14.04.2002 added MotionEstimationBVOP()  
  *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between  
  *             EPZS and EPZS^2  
  *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop  
  *             PMVFast_Refine to support multiple searches with different start points  
  *  07.01.2002 uv-block-based interpolation  
  *  06.01.2002 INTER/INTRA-decision is now done before any SEARCH8 (speedup)  
  *             changed INTER_BIAS to 150 (as suggested by suxen_drol)  
  *             removed halfpel refinement step in PMVfastSearch8 + quality=5  
  *             added new quality mode = 6 which performs halfpel refinement  
  *             filesize difference between quality 5 and 6 is smaller than 1%  
  *             (Isibaar)  
  *  31.12.2001 PMVfastSearch16 and PMVfastSearch8 (gruel)  
  *  30.12.2001 get_range/MotionSearchX simplified; blue/green bug fix  
  *  22.12.2001 commented best_point==99 check  
  *  19.12.2001 modified get_range (purple bug fix)  
  *  15.12.2001 moved pmv displacement from mbprediction  
  *  02.12.2001 motion estimation/compensation split (Isibaar)  
  *  16.11.2001 rewrote/tweaked search algorithms; pross@cs.rmit.edu.au  
  *  10.11.2001 support for sad16/sad8 functions  
  *  28.08.2001 reactivated MODE_INTER4V for EXT_MODE  
  *  24.08.2001 removed MODE_INTER4V_Q, disabled MODE_INTER4V for EXT_MODE  
  *  22.08.2001 added MODE_INTER4V_Q  
  *  20.08.2001 added pragma to get rid of internal compiler error with VC6  
  *             idea by Cyril. Thanks.  
9   *   *
10   *  Michael Militzer <isibaar@videocoding.de>   *  This program is an implementation of a part of one or more MPEG-4
11     *  Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
12     *  to use this software module in hardware or software products are
13     *  advised that its use may infringe existing patents or copyrights, and
14     *  any such use would be at such party's own risk.  The original
15     *  developer of this software module and his/her company, and subsequent
16     *  editors and their companies, will have no liability for use of this
17     *  software or modifications or derivatives thereof.
18   *   *
19   **************************************************************************/   *  This program is free software; you can redistribute it and/or modify
20     *  it under the terms of the GNU General Public License as published by
21     *  the Free Software Foundation; either version 2 of the License, or
22     *  (at your option) any later version.
23     *
24     *  This program is distributed in the hope that it will be useful,
25     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
26     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27     *  GNU General Public License for more details.
28     *
29     *  You should have received a copy of the GNU General Public License
30     *  along with this program; if not, write to the Free Software
31     *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
32     *
33     *************************************************************************/
34    
35  #include <assert.h>  #include <assert.h>
36  #include <stdio.h>  #include <stdio.h>
# Line 47  Line 44 
44  #include "motion.h"  #include "motion.h"
45  #include "sad.h"  #include "sad.h"
46    
 // very large value  
 #define MV_MAX_ERROR    (4096 * 256)  
   
 // stop search if sdelta < THRESHOLD  
 #define MV16_THRESHOLD  192  
 #define MV8_THRESHOLD   56  
   
 #define NEIGH_MOVE_THRESH 0  
 // how much a block's MV must differ from his neighbour  
 // to be search for INTER4V. The more, the faster...  
   
 /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  
 /* nb  = vop pixels * 2^(bpp-8) */  
 #define MV16_00_BIAS    (128+1)  
 #define MV8_00_BIAS     (0)  
   
 /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */  
 #define MV16_INTER_BIAS 512  
   
 /* Parameters which control inter/inter4v decision */  
 #define IMV16X16                        5  
   
 /* vector map (vlc delta size) smoother parameters */  
 #define NEIGH_TEND_16X16        2  
 #define NEIGH_TEND_8X8          2  
   
 // fast ((A)/2)*2  
 #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  
   
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
 int32_t PMVfastSearch16(const uint8_t * const pRef,  
                                                 const uint8_t * const pRefH,  
                                                 const uint8_t * const pRefV,  
                                                 const uint8_t * const pRefHV,  
                                                 const IMAGE * const pCur,  
                                                 const int x,  
                                                 const int y,  
                                                 const uint32_t MotionFlags,  
                                                 const uint32_t iQuant,  
                                                 const uint32_t iFcode,  
                                                 const MBParam * const pParam,  
                                                 const MACROBLOCK * const pMBs,  
                                                 const MACROBLOCK * const prevMBs,  
                                                 VECTOR * const currMV,  
                                                 VECTOR * const currPMV);  
   
 int32_t EPZSSearch16(const uint8_t * const pRef,  
                                          const uint8_t * const pRefH,  
                                          const uint8_t * const pRefV,  
                                          const uint8_t * const pRefHV,  
                                          const IMAGE * const pCur,  
                                          const int x,  
                                          const int y,  
                                          const uint32_t MotionFlags,  
                                          const uint32_t iQuant,  
                                          const uint32_t iFcode,  
                                          const MBParam * const pParam,  
                                          const MACROBLOCK * const pMBs,  
                                          const MACROBLOCK * const prevMBs,  
                                          VECTOR * const currMV,  
                                          VECTOR * const currPMV);  
   
   
 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);  
   
47    
 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),  { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),
# Line 274  Line 122 
122                                                                                                     mv_bits(dy, iFcode));                                                                                                     mv_bits(dy, iFcode));
123  }  }
124    
   
   
   
   
 #ifndef SEARCH16  
 #define SEARCH16        PMVfastSearch16  
 //#define SEARCH16  FullSearch16  
 //#define SEARCH16  EPZSSearch16  
 #endif  
   
 #ifndef SEARCH8  
 #define SEARCH8         PMVfastSearch8  
 //#define SEARCH8   EPZSSearch8  
 #endif  
   
125  bool  bool
126  MotionEstimation(MBParam * const pParam,  MotionEstimation(MBParam * const pParam,
127                                   FRAMEINFO * const current,                                   FRAMEINFO * const current,
# Line 305  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                            if (pMB->mode == MODE_NOT_CODED)
157                                    continue;
158    
159                            predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
160    
161                          pMB->sad16 =                          pMB->sad16 =
162                                  SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                                  SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
163                                                   y, current->motion_flags, current->quant,                                                   x, y, predMV.x, predMV.y, predMV.x, predMV.y,
164                                                     current->motion_flags, current->quant,
165                                                   current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,                                                   current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
166                                                   &pMB->pmvs[0]);                                                   &pMB->pmvs[0]);
167    
# Line 352  Line 193 
193                                           pMB->dquant == NO_CHANGE)) {                                           pMB->dquant == NO_CHANGE)) {
194                                          int32_t sad8 = IMV16X16 * current->quant;                                          int32_t sad8 = IMV16X16 * current->quant;
195    
196                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16) {
   
197                                                  sad8 += pMB->sad8[0] =                                                  sad8 += pMB->sad8[0] =
198                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
199                                                                          pCurrent, 2 * x, 2 * y, pMB->mv16.x,                                                                          pCurrent, 2 * x, 2 * y,
200                                                                          pMB->mv16.y, current->motion_flags,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
201                                                                            current->motion_flags,
202                                                                          current->quant, current->fcode, pParam,                                                                          current->quant, current->fcode, pParam,
203                                                                          pMBs, prevMBs, &pMB->mvs[0],                                                                          pMBs, prevMBs, &pMB->mvs[0],
204                                                                          &pMB->pmvs[0]);                                                                          &pMB->pmvs[0]);
205                                            }
206                                            if (sad8 < pMB->sad16) {
207    
208                                          if (sad8 < pMB->sad16)                                                  predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
209                                                  sad8 += pMB->sad8[1] =                                                  sad8 += pMB->sad8[1] =
210                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
211                                                                          pCurrent, 2 * x + 1, 2 * y, pMB->mv16.x,                                                                          pCurrent, 2 * x + 1, 2 * y,
212                                                                          pMB->mv16.y, current->motion_flags,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
213                                                                            current->motion_flags,
214                                                                          current->quant, current->fcode, pParam,                                                                          current->quant, current->fcode, pParam,
215                                                                          pMBs, prevMBs, &pMB->mvs[1],                                                                          pMBs, prevMBs, &pMB->mvs[1],
216                                                                          &pMB->pmvs[1]);                                                                          &pMB->pmvs[1]);
217                                            }
218                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16) {
219                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
220                                                  sad8 += pMB->sad8[2] =                                                  sad8 += pMB->sad8[2] =
221                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
222                                                                          pCurrent, 2 * x, 2 * y + 1, pMB->mv16.x,                                                                          pCurrent, 2 * x, 2 * y + 1,
223                                                                          pMB->mv16.y, current->motion_flags,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
224                                                                            current->motion_flags,
225                                                                          current->quant, current->fcode, pParam,                                                                          current->quant, current->fcode, pParam,
226                                                                          pMBs, prevMBs, &pMB->mvs[2],                                                                          pMBs, prevMBs, &pMB->mvs[2],
227                                                                          &pMB->pmvs[2]);                                                                          &pMB->pmvs[2]);
228                                            }
229                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16) {
230                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
231                                                  sad8 += pMB->sad8[3] =                                                  sad8 += pMB->sad8[3] =
232                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
233                                                                          pCurrent, 2 * x + 1, 2 * y + 1,                                                                          pCurrent, 2 * x + 1, 2 * y + 1,
234                                                                          pMB->mv16.x, pMB->mv16.y,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
235                                                                          current->motion_flags, current->quant,                                                                          current->motion_flags,
236                                                                          current->fcode, pParam, pMBs, prevMBs,                                                                          current->quant, current->fcode, pParam,
237                                                                          &pMB->mvs[3], &pMB->pmvs[3]);                                                                          pMBs, prevMBs,
238                                                                            &pMB->mvs[3],
239                                                                            &pMB->pmvs[3]);
240                                            }
241    
242                                          /* decide: MODE_INTER or MODE_INTER4V                                          /* decide: MODE_INTER or MODE_INTER4V
243                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
# Line 409  Line 259 
259                          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;
260                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
261                                  pMB->sad16;                                  pMB->sad16;
   
262                  }                  }
263                            }
264    
265          return 0;          return 0;
266  }  }
267    
268    
269  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
270    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
271      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
272    { \    { \
273      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \
274      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
275      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
276      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
277  }  }
278    
279  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
280      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
281      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
282      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
283      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
284  }  }
# Line 436  Line 288 
288      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
289    { \    { \
290      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
291      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
292      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
293      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
294  }  }
# Line 446  Line 298 
298      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
299    { \    { \
300      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
301      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
302      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
303      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
304  }  }
# Line 456  Line 308 
308      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
309    { \    { \
310      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
311      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
312      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
313      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
314  }  }
# Line 464  Line 316 
316    
317  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
318    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \
319    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\    iSAD += calc_delta_8(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
320    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
321    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
322  }  }
# Line 472  Line 324 
324  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
325    { \    { \
326      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
327      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
328      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
329      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
330  }  }
# Line 482  Line 334 
334      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
335    { \    { \
336      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
337      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
338      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
339      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
340  }  }
# Line 492  Line 344 
344      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
345    { \    { \
346      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
347      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
348      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
349      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
350  }  }
# Line 502  Line 354 
354      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
355    { \    { \
356      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
357      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
358      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
359      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
360  }  }
# Line 528  Line 380 
380          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
381          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
382          int32_t iSAD;          int32_t iSAD;
383          int32_t pred_x,pred_y;          VECTOR pred;
384    
385          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);  
386            pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
387    
388          iSAD = sad16( cur,          iSAD = sad16( cur,
389                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
# Line 540  Line 393 
393    
394          currMV->x = 0;          currMV->x = 0;
395          currMV->y = 0;          currMV->y = 0;
396          currPMV->x = -pred_x;          currPMV->x = -pred.x;
397          currPMV->y = -pred_y;          currPMV->y = -pred.y;
398    
399          return iSAD;          return iSAD;
400    
# Line 556  Line 409 
409                                           const uint8_t * const cur,                                           const uint8_t * const cur,
410                                           const int x,                                           const int x,
411                                           const int y,                                           const int y,
412                                           int32_t startx,                                           const int start_x,
413                                           int32_t starty,                                           const int start_y,
414                                           int32_t iMinSAD,                                           int iMinSAD,
415                                           VECTOR * const currMV,                                           VECTOR * const currMV,
416                                           const VECTOR * const pmv,                                           const int center_x,
417                                             const int center_y,
418                                           const int32_t min_dx,                                           const int32_t min_dx,
419                                           const int32_t max_dx,                                           const int32_t max_dx,
420                                           const int32_t min_dy,                                           const int32_t min_dy,
# Line 574  Line 428 
428  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
429    
430          int32_t iDirection = 0;          int32_t iDirection = 0;
431            int32_t iDirectionBackup;
432          int32_t iSAD;          int32_t iSAD;
433          VECTOR backupMV;          VECTOR backupMV;
434    
435          backupMV.x = startx;          backupMV.x = start_x;
436          backupMV.y = starty;          backupMV.y = start_y;
437    
438  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
439    
# Line 587  Line 442 
442          CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
443          CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
444    
445          if (iDirection)          if (iDirection) {
446                  while (!iFound) {                  while (!iFound) {
447                          iFound = 1;                          iFound = 1;
448                          backupMV = *currMV;                          backupMV = *currMV;
449                            iDirectionBackup = iDirection;
450    
451                          if (iDirection != 2)                          if (iDirectionBackup != 2)
452                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
453                                                                                     backupMV.y, 1);                                                                                     backupMV.y, 1);
454                          if (iDirection != 1)                          if (iDirectionBackup != 1)
455                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
456                                                                                     backupMV.y, 2);                                                                                     backupMV.y, 2);
457                          if (iDirection != 4)                          if (iDirectionBackup != 4)
458                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
459                                                                                     backupMV.y - iDiamondSize, 3);                                                                                     backupMV.y - iDiamondSize, 3);
460                          if (iDirection != 3)                          if (iDirectionBackup != 3)
461                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
462                                                                                     backupMV.y + iDiamondSize, 4);                                                                                     backupMV.y + iDiamondSize, 4);
463                    }
464          } else {          } else {
465                  currMV->x = startx;                  currMV->x = start_x;
466                  currMV->y = starty;                  currMV->y = start_y;
467          }          }
468          return iMinSAD;          return iMinSAD;
469  }  }
# Line 619  Line 476 
476                                          const uint8_t * const cur,                                          const uint8_t * const cur,
477                                          const int x,                                          const int x,
478                                          const int y,                                          const int y,
479                                          int32_t startx,                                          const int start_x,
480                                          int32_t starty,                                          const int start_y,
481                                          int32_t iMinSAD,                                          int iMinSAD,
482                                          VECTOR * const currMV,                                          VECTOR * const currMV,
483                                          const VECTOR * const pmv,                                          const int center_x,
484                                            const int center_y,
485                                          const int32_t min_dx,                                          const int32_t min_dx,
486                                          const int32_t max_dx,                                          const int32_t max_dx,
487                                          const int32_t min_dy,                                          const int32_t min_dy,
# Line 640  Line 498 
498          int32_t iSAD;          int32_t iSAD;
499          VECTOR backupMV;          VECTOR backupMV;
500    
501          backupMV.x = startx;          backupMV.x = start_x;
502          backupMV.y = starty;          backupMV.y = start_y;
503    
504  /* It's one search with full square pattern, and new parts for all following diamonds */  /* It's one search with full square pattern, and new parts for all following diamonds */
505    
# Line 666  Line 524 
524                                                           backupMV.y + iDiamondSize, 8);                                                           backupMV.y + iDiamondSize, 8);
525    
526    
527          if (iDirection)          if (iDirection) {
528                  while (!iFound) {                  while (!iFound) {
529                          iFound = 1;                          iFound = 1;
530                          backupMV = *currMV;                          backupMV = *currMV;
# Line 675  Line 533 
533                          case 1:                          case 1:
534                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
535                                                                                     backupMV.y, 1);                                                                                     backupMV.y, 1);
536                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
537                                                                                   backupMV.y - iDiamondSize, 5);                                                                                   backupMV.y - iDiamondSize, 5);
538                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
539                                                                                   backupMV.y - iDiamondSize, 7);                                                                                   backupMV.y - iDiamondSize, 7);
540                                  break;                                  break;
541                          case 2:                          case 2:
542                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
543                                                                                   2);                                                                                   2);
544                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
545                                                                                   backupMV.y + iDiamondSize, 6);                                                                                   backupMV.y + iDiamondSize, 6);
546                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
547                                                                                   backupMV.y + iDiamondSize, 8);                                                                                   backupMV.y + iDiamondSize, 8);
548                                  break;                                  break;
549    
550                          case 3:                          case 3:
551                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
552                                                                                   4);                                                                                   4);
553                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
554                                                                                   backupMV.y - iDiamondSize, 7);                                                                                   backupMV.y - iDiamondSize, 7);
555                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
556                                                                                   backupMV.y + iDiamondSize, 8);                                                                                   backupMV.y + iDiamondSize, 8);
557                                  break;                                  break;
558    
559                          case 4:                          case 4:
560                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
561                                                                                   3);                                                                                   3);
562                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
563                                                                                   backupMV.y - iDiamondSize, 5);                                                                                   backupMV.y - iDiamondSize, 5);
564                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
565                                                                                   backupMV.y + iDiamondSize, 6);                                                                                   backupMV.y + iDiamondSize, 6);
566                                  break;                                  break;
567    
568                          case 5:                          case 5:
569                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
570                                                                                   1);                                                                                   1);
571                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
572                                                                                   3);                                                                                   3);
573                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
574                                                                                   backupMV.y - iDiamondSize, 5);                                                                                   backupMV.y - iDiamondSize, 5);
575                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
576                                                                                   backupMV.y + iDiamondSize, 6);                                                                                   backupMV.y + iDiamondSize, 6);
577                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
578                                                                                   backupMV.y - iDiamondSize, 7);                                                                                   backupMV.y - iDiamondSize, 7);
579                                  break;                                  break;
580    
581                          case 6:                          case 6:
582                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
583                                                                                   2);                                                                                   2);
584                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
585                                                                                   3);                                                                                   3);
586    
587                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
588                                                                                   backupMV.y - iDiamondSize, 5);                                                                                   backupMV.y - iDiamondSize, 5);
589                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
590                                                                                   backupMV.y + iDiamondSize, 6);                                                                                   backupMV.y + iDiamondSize, 6);
591                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
592                                                                                   backupMV.y + iDiamondSize, 8);                                                                                   backupMV.y + iDiamondSize, 8);
593    
594                                  break;                                  break;
# Line 738  Line 596 
596                          case 7:                          case 7:
597                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
598                                                                                     backupMV.y, 1);                                                                                     backupMV.y, 1);
599                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
600                                                                                   4);                                                                                   4);
601                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
602                                                                                   backupMV.y - iDiamondSize, 5);                                                                                   backupMV.y - iDiamondSize, 5);
603                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
604                                                                                   backupMV.y - iDiamondSize, 7);                                                                                   backupMV.y - iDiamondSize, 7);
605                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
606                                                                                   backupMV.y + iDiamondSize, 8);                                                                                   backupMV.y + iDiamondSize, 8);
607                                  break;                                  break;
608    
609                          case 8:                          case 8:
610                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
611                                                                                   2);                                                                                   2);
612                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
613                                                                                   4);                                                                                   4);
614                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
615                                                                                   backupMV.y + iDiamondSize, 6);                                                                                   backupMV.y + iDiamondSize, 6);
616                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
617                                                                                   backupMV.y - iDiamondSize, 7);                                                                                   backupMV.y - iDiamondSize, 7);
618                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
619                                                                                   backupMV.y + iDiamondSize, 8);                                                                                   backupMV.y + iDiamondSize, 8);
620                                  break;                                  break;
621                          default:                          default:
622                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
623                                                                                   1);                                                                                   1);
624                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
625                                                                                   2);                                                                                   2);
626                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
627                                                                                   3);                                                                                   3);
628                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
629                                                                                   4);                                                                                   4);
630    
631                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
632                                                                                   backupMV.y - iDiamondSize, 5);                                                                                   backupMV.y - iDiamondSize, 5);
633                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
634                                                                                   backupMV.y + iDiamondSize, 6);                                                                                   backupMV.y + iDiamondSize, 6);
635                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
636                                                                                   backupMV.y - iDiamondSize, 7);                                                                                   backupMV.y - iDiamondSize, 7);
637                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
638                                                                                   backupMV.y + iDiamondSize, 8);                                                                                   backupMV.y + iDiamondSize, 8);
639                                  break;                                  break;
640                          }                          }
641                    }
642          } else {          } else {
643                  currMV->x = startx;                  currMV->x = start_x;
644                  currMV->y = starty;                  currMV->y = start_y;
645          }          }
646          return iMinSAD;          return iMinSAD;
647  }  }
# Line 796  Line 655 
655                                    const uint8_t * const cur,                                    const uint8_t * const cur,
656                                    const int x,                                    const int x,
657                                    const int y,                                    const int y,
658                                    int32_t startx,                                    const int start_x,
659                                    int32_t starty,                                    const int start_y,
660                                    int32_t iMinSAD,                                    int iMinSAD,
661                                    VECTOR * const currMV,                                    VECTOR * const currMV,
662                                    const VECTOR * const pmv,                                    const int center_x,
663                                      const int center_y,
664                                    const int32_t min_dx,                                    const int32_t min_dx,
665                                    const int32_t max_dx,                                    const int32_t max_dx,
666                                    const int32_t min_dy,                                    const int32_t min_dy,
# Line 815  Line 675 
675          int32_t dx, dy;          int32_t dx, dy;
676          VECTOR backupMV;          VECTOR backupMV;
677    
678          backupMV.x = startx;          backupMV.x = start_x;
679          backupMV.y = starty;          backupMV.y = start_y;
680    
681          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
682                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
# Line 833  Line 693 
693                                                  const uint8_t * const cur,                                                  const uint8_t * const cur,
694                                                  const int x,                                                  const int x,
695                                                  const int y,                                                  const int y,
696                                                  int32_t startx,                                                  const int start_xi,
697                                                  int32_t starty,                                                  const int start_yi,
698                                                  int32_t iMinSAD,                                                  int iMinSAD,
699                                                  VECTOR * const currMV,                                                  VECTOR * const currMV,
700                                                  const VECTOR * const pmv,                                                  const int center_x,
701                                                    const int center_y,
702                                                  const int32_t min_dx,                                                  const int32_t min_dx,
703                                                  const int32_t max_dx,                                                  const int32_t max_dx,
704                                                  const int32_t min_dy,                                                  const int32_t min_dy,
# Line 850  Line 711 
711  {  {
712    
713          int32_t iSAD;          int32_t iSAD;
714            int start_x = start_xi, start_y = start_yi;
715    
716  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
717    
718          if (iDirection) {          if (iDirection) {
719                  CHECK_MV16_CANDIDATE(startx - iDiamondSize, starty);                  CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
720                  CHECK_MV16_CANDIDATE(startx + iDiamondSize, starty);                  CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
721                  CHECK_MV16_CANDIDATE(startx, starty - iDiamondSize);                  CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
722                  CHECK_MV16_CANDIDATE(startx, starty + iDiamondSize);                  CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
723          } else {          } else {
724                  int bDirection = 1 + 2 + 4 + 8;                  int bDirection = 1 + 2 + 4 + 8;
725    
726                  do {                  do {
727                          iDirection = 0;                          iDirection = 0;
728                          if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)                          if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
729                                  CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);                                  CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
730    
731                          if (bDirection & 2)                          if (bDirection & 2)
732                                  CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);                                  CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
733    
734                          if (bDirection & 4)                          if (bDirection & 4)
735                                  CHECK_MV16_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
736    
737                          if (bDirection & 8)                          if (bDirection & 8)
738                                  CHECK_MV16_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
739    
740                          /* now we're doing diagonal checks near our candidate */                          /* now we're doing diagonal checks near our candidate */
741    
# Line 881  Line 743 
743                          {                          {
744                                  bDirection = iDirection;                                  bDirection = iDirection;
745                                  iDirection = 0;                                  iDirection = 0;
746                                  startx = currMV->x;                                  start_x = currMV->x;
747                                  starty = currMV->y;                                  start_y = currMV->y;
748                                  if (bDirection & 3)     //our candidate is left or right                                  if (bDirection & 3)     //our candidate is left or right
749                                  {                                  {
750                                          CHECK_MV16_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);                                          CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
751                                          CHECK_MV16_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);                                          CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
752                                  } else                  // what remains here is up or down                                  } else                  // what remains here is up or down
753                                  {                                  {
754                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
755                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
756                                  }                                  }
757    
758                                  if (iDirection) {                                  if (iDirection) {
759                                          bDirection += iDirection;                                          bDirection += iDirection;
760                                          startx = currMV->x;                                          start_x = currMV->x;
761                                          starty = currMV->y;                                          start_y = currMV->y;
762                                  }                                  }
763                          } else                          //about to quit, eh? not so fast....                          } else                          //about to quit, eh? not so fast....
764                          {                          {
765                                  switch (bDirection) {                                  switch (bDirection) {
766                                  case 2:                                  case 2:
767                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
768                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
769                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
770                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
771                                          break;                                          break;
772                                  case 1:                                  case 1:
773                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,  
774                                                                                           starty - iDiamondSize, 1 + 4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
775                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                                                                           start_y - iDiamondSize, 1 + 4);
776                                                                                           starty + iDiamondSize, 1 + 8);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
777                                                                                             start_y + iDiamondSize, 1 + 8);
778                                          break;                                          break;
779                                  case 2 + 4:                                  case 2 + 4:
780                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
781                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
782                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
783                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
784                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
785                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
786                                          break;                                          break;
787                                  case 4:                                  case 4:
788                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
789                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
790                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
791                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
792                                          break;                                          break;
793                                  case 8:                                  case 8:
794                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
795                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
796                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
797                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
798                                          break;                                          break;
799                                  case 1 + 4:                                  case 1 + 4:
800                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
801                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
802                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
803                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
804                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
805                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
806                                          break;                                          break;
807                                  case 2 + 8:                                  case 2 + 8:
808                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
809                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
810                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
811                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
812                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
813                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
814                                          break;                                          break;
815                                  case 1 + 8:                                  case 1 + 8:
816                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
817                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
818                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
819                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
820                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
821                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
822                                          break;                                          break;
823                                  default:                //1+2+4+8 == we didn't find anything at all                                  default:                //1+2+4+8 == we didn't find anything at all
824                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
825                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
826                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
827                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
828                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
829                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
830                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
831                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
832                                          break;                                          break;
833                                  }                                  }
834                                  if (!iDirection)                                  if (!iDirection)
835                                          break;          //ok, the end. really                                          break;          //ok, the end. really
836                                  else {                                  else {
837                                          bDirection = iDirection;                                          bDirection = iDirection;
838                                          startx = currMV->x;                                          start_x = currMV->x;
839                                          starty = currMV->y;                                          start_y = currMV->y;
840                                  }                                  }
841                          }                          }
842                  }                  }
# Line 982  Line 845 
845          return iMinSAD;          return iMinSAD;
846  }  }
847    
848    #define CHECK_MV16_F_INTERPOL(X,Y) { \
849      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
850        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
851      { \
852        iSAD = sad16bi( cur, \
853                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
854                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
855                            iEdgedWidth); \
856        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
857        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
858        if (iSAD < iMinSAD) \
859        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); } } \
860    }
861    
862    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y) { \
863      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
864        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
865      { \
866        iSAD = sad16bi( cur, \
867                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
868                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
869                            iEdgedWidth); \
870        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
871        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
872        if (iSAD < iMinSAD) \
873        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); iFound=0;} } \
874    }
875    
876    #define CHECK_MV16_B_INTERPOL(X,Y) { \
877      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
878        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
879      { \
880        iSAD = sad16bi( cur, \
881                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
882                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
883                            iEdgedWidth); \
884        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
885        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
886        if (iSAD < iMinSAD) \
887        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); } } \
888    }
889    
890    #define CHECK_MV16_B_INTERPOL_FOUND(X,Y) { \
891      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
892        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
893      { \
894        iSAD = sad16bi( cur, \
895                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
896                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
897                            iEdgedWidth); \
898        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
899        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
900        if (iSAD < iMinSAD) \
901        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); iFound=0;} } \
902    }
903    
904    int32_t
905    Diamond16_InterpolMainSearch(const uint8_t * const f_pRef,
906                                                             const uint8_t * const f_pRefH,
907                                                             const uint8_t * const f_pRefV,
908                                                             const uint8_t * const f_pRefHV,
909    
910                                                             const uint8_t * const cur,
911    
912                                                             const uint8_t * const b_pRef,
913                                                             const uint8_t * const b_pRefH,
914                                                             const uint8_t * const b_pRefV,
915                                                             const uint8_t * const b_pRefHV,
916    
917                                                             const int x,
918                                                             const int y,
919    
920                                                             const int f_start_x,
921                                                             const int f_start_y,
922                                                             const int b_start_x,
923                                                             const int b_start_y,
924    
925                                                             int iMinSAD,
926                                                             VECTOR * const f_currMV,
927                                                             VECTOR * const b_currMV,
928    
929                                                             const int f_center_x,
930                                                             const int f_center_y,
931                                                             const int b_center_x,
932                                                             const int b_center_y,
933    
934                                                             const int32_t f_min_dx,
935                                                             const int32_t f_max_dx,
936                                                             const int32_t f_min_dy,
937                                                             const int32_t f_max_dy,
938    
939                                                             const int32_t b_min_dx,
940                                                             const int32_t b_max_dx,
941                                                             const int32_t b_min_dy,
942                                                             const int32_t b_max_dy,
943    
944                                                             const int32_t iEdgedWidth,
945                                                             const int32_t iDiamondSize,
946    
947                                                             const int32_t f_iFcode,
948                                                             const int32_t b_iFcode,
949    
950                                                             const int32_t iQuant,
951                                                             int iFound)
952    {
953    /* Do a diamond search around given starting point, return SAD of best */
954    
955            int32_t iSAD;
956    
957            VECTOR f_backupMV;
958            VECTOR b_backupMV;
959    
960            f_currMV->x = f_start_x;
961            f_currMV->y = f_start_y;
962            b_currMV->x = b_start_x;
963            b_currMV->y = b_start_y;
964    
965            do
966            {
967                    iFound = 1;
968    
969                    f_backupMV = *f_currMV;
970    
971                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x - iDiamondSize, f_backupMV.y);
972                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x + iDiamondSize, f_backupMV.y);
973                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y - iDiamondSize);
974                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y + iDiamondSize);
975    
976                    b_backupMV = *b_currMV;
977    
978                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x - iDiamondSize, b_backupMV.y);
979                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x + iDiamondSize, b_backupMV.y);
980                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y - iDiamondSize);
981                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y + iDiamondSize);
982    
983            } while (!iFound);
984    
985            return iMinSAD;
986    }
987    
988    /* Sorry, these MACROS really got too large... I'll turn them into function soon! */
989    
990    #define CHECK_MV16_DIRECT_FOUND(X,Y) \
991            if ( (X)>=(-32) && (X)<=(31) && ((Y)>=-32) && ((Y)<=31) ) \
992            { int k;\
993            VECTOR mvs,b_mvs;       \
994            iSAD = 0;\
995            for (k = 0; k < 4; k++) {       \
996                                            mvs.x = (int32_t) ((TRB * directmv[k].x) / TRD + (X));          \
997                        b_mvs.x = (int32_t) (((X) == 0)                                                     \
998                                                                                    ? ((TRB - TRD) * directmv[k].x) / TRD   \
999                                                : mvs.x - directmv[k].x);                           \
1000                                                                                                                                                                    \
1001                        mvs.y = (int32_t) ((TRB * directmv[k].y) / TRD + (Y));              \
1002                            b_mvs.y = (int32_t) (((Y) == 0)                                                         \
1003                                                                                    ? ((TRB - TRD) * directmv[k].y) / TRD   \
1004                                                : mvs.y - directmv[k].y);                           \
1005                                                                                                                                                                    \
1006      if ( (mvs.x <= max_dx) && (mvs.x >= min_dx) \
1007        && (mvs.y <= max_dy) && (mvs.y >= min_dy)  \
1008            && (b_mvs.x <= max_dx) && (b_mvs.x >= min_dx)  \
1009        && (b_mvs.y <= max_dy) && (b_mvs.y >= min_dy) ) { \
1010                iSAD += sad8bi( cur + 8*(k&1) + 8*(k>>1)*iEdgedWidth,                                                                                                       \
1011                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1012                                            mvs.x, mvs.y, iEdgedWidth),                                                             \
1013                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1014                                            b_mvs.x, b_mvs.y, iEdgedWidth),                                                         \
1015                            iEdgedWidth); \
1016                    }       \
1017            else    \
1018                    iSAD = 65535;   \
1019            } \
1020            iSAD += calc_delta_16((X),(Y), 1, iQuant);\
1021            if (iSAD < iMinSAD) \
1022                {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iFound=0; } \
1023    }
1024    
1025    
1026    
1027    int32_t
1028    Diamond16_DirectMainSearch(
1029                                            const uint8_t * const f_pRef,
1030                                            const uint8_t * const f_pRefH,
1031                                            const uint8_t * const f_pRefV,
1032                                            const uint8_t * const f_pRefHV,
1033    
1034                                            const uint8_t * const cur,
1035    
1036                                            const uint8_t * const b_pRef,
1037                                            const uint8_t * const b_pRefH,
1038                                            const uint8_t * const b_pRefV,
1039                                            const uint8_t * const b_pRefHV,
1040    
1041                                            const int x,
1042                                            const int y,
1043    
1044                                            const int TRB,
1045                                            const int TRD,
1046    
1047                                        const int start_x,
1048                                        const int start_y,
1049    
1050                                        int iMinSAD,
1051                                        VECTOR * const currMV,
1052                                            const VECTOR * const directmv,
1053    
1054                                        const int32_t min_dx,
1055                                            const int32_t max_dx,
1056                                            const int32_t min_dy,
1057                                            const int32_t max_dy,
1058    
1059                                            const int32_t iEdgedWidth,
1060                                            const int32_t iDiamondSize,
1061    
1062                                            const int32_t iQuant,
1063                                            int iFound)
1064    {
1065    /* Do a diamond search around given starting point, return SAD of best */
1066    
1067            int32_t iSAD;
1068    
1069            VECTOR backupMV;
1070    
1071            currMV->x = start_x;
1072            currMV->y = start_y;
1073    
1074    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1075    
1076            do
1077            {
1078                    iFound = 1;
1079    
1080                    backupMV = *currMV;
1081    
1082                    CHECK_MV16_DIRECT_FOUND(backupMV.x - iDiamondSize, backupMV.y);
1083                    CHECK_MV16_DIRECT_FOUND(backupMV.x + iDiamondSize, backupMV.y);
1084                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y - iDiamondSize);
1085                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y + iDiamondSize);
1086    
1087            } while (!iFound);
1088    
1089            return iMinSAD;
1090    }
1091    
1092    
1093  int32_t  int32_t
1094  AdvDiamond8_MainSearch(const uint8_t * const pRef,  AdvDiamond8_MainSearch(const uint8_t * const pRef,
1095                                             const uint8_t * const pRefH,                                             const uint8_t * const pRefH,
# Line 990  Line 1098 
1098                                             const uint8_t * const cur,                                             const uint8_t * const cur,
1099                                             const int x,                                             const int x,
1100                                             const int y,                                             const int y,
1101                                             int32_t startx,                                             const int start_xi,
1102                                             int32_t starty,                                             const int start_yi,
1103                                             int32_t iMinSAD,                                             int iMinSAD,
1104                                             VECTOR * const currMV,                                             VECTOR * const currMV,
1105                                             const VECTOR * const pmv,                                             const int center_x,
1106                                               const int center_y,
1107                                             const int32_t min_dx,                                             const int32_t min_dx,
1108                                             const int32_t max_dx,                                             const int32_t max_dx,
1109                                             const int32_t min_dy,                                             const int32_t min_dy,
# Line 1007  Line 1116 
1116  {  {
1117    
1118          int32_t iSAD;          int32_t iSAD;
1119            int start_x = start_xi, start_y = start_yi;
1120    
1121  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1122    
1123          if (iDirection) {          if (iDirection) {
1124                  CHECK_MV8_CANDIDATE(startx - iDiamondSize, starty);                  CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1125                  CHECK_MV8_CANDIDATE(startx + iDiamondSize, starty);                  CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1126                  CHECK_MV8_CANDIDATE(startx, starty - iDiamondSize);                  CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1127                  CHECK_MV8_CANDIDATE(startx, starty + iDiamondSize);                  CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1128          } else {          } else {
1129                  int bDirection = 1 + 2 + 4 + 8;                  int bDirection = 1 + 2 + 4 + 8;
1130    
1131                  do {                  do {
1132                          iDirection = 0;                          iDirection = 0;
1133                          if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)                          if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
1134                                  CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);                                  CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1135    
1136                          if (bDirection & 2)                          if (bDirection & 2)
1137                                  CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);                                  CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1138    
1139                          if (bDirection & 4)                          if (bDirection & 4)
1140                                  CHECK_MV8_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);                                  CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1141    
1142                          if (bDirection & 8)                          if (bDirection & 8)
1143                                  CHECK_MV8_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);                                  CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1144    
1145                          /* now we're doing diagonal checks near our candidate */                          /* now we're doing diagonal checks near our candidate */
1146    
# Line 1038  Line 1148 
1148                          {                          {
1149                                  bDirection = iDirection;                                  bDirection = iDirection;
1150                                  iDirection = 0;                                  iDirection = 0;
1151                                  startx = currMV->x;                                  start_x = currMV->x;
1152                                  starty = currMV->y;                                  start_y = currMV->y;
1153                                  if (bDirection & 3)     //our candidate is left or right                                  if (bDirection & 3)     //our candidate is left or right
1154                                  {                                  {
1155                                          CHECK_MV8_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1156                                          CHECK_MV8_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1157                                  } else                  // what remains here is up or down                                  } else                  // what remains here is up or down
1158                                  {                                  {
1159                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1160                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1161                                  }                                  }
1162    
1163                                  if (iDirection) {                                  if (iDirection) {
1164                                          bDirection += iDirection;                                          bDirection += iDirection;
1165                                          startx = currMV->x;                                          start_x = currMV->x;
1166                                          starty = currMV->y;                                          start_y = currMV->y;
1167                                  }                                  }
1168                          } else                          //about to quit, eh? not so fast....                          } else                          //about to quit, eh? not so fast....
1169                          {                          {
1170                                  switch (bDirection) {                                  switch (bDirection) {
1171                                  case 2:                                  case 2:
1172                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1173                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1174                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1175                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1176                                          break;                                          break;
1177                                  case 1:                                  case 1:
1178                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1179                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1180                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1181                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1182                                          break;                                          break;
1183                                  case 2 + 4:                                  case 2 + 4:
1184                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1185                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1186                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1187                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1188                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1189                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1190                                          break;                                          break;
1191                                  case 4:                                  case 4:
1192                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1193                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1194                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1195                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1196                                          break;                                          break;
1197                                  case 8:                                  case 8:
1198                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1199                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1200                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1201                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1202                                          break;                                          break;
1203                                  case 1 + 4:                                  case 1 + 4:
1204                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1205                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1206                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1207                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1208                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1209                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1210                                          break;                                          break;
1211                                  case 2 + 8:                                  case 2 + 8:
1212                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1213                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1214                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1215                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1216                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1217                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1218                                          break;                                          break;
1219                                  case 1 + 8:                                  case 1 + 8:
1220                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1221                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1222                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1223                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1224                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1225                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1226                                          break;                                          break;
1227                                  default:                //1+2+4+8 == we didn't find anything at all                                  default:                //1+2+4+8 == we didn't find anything at all
1228                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1229                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1230                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1231                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1232                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1233                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1234                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1235                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1236                                          break;                                          break;
1237                                  }                                  }
1238                                  if (!(iDirection))                                  if (!(iDirection))
1239                                          break;          //ok, the end. really                                          break;          //ok, the end. really
1240                                  else {                                  else {
1241                                          bDirection = iDirection;                                          bDirection = iDirection;
1242                                          startx = currMV->x;                                          start_x = currMV->x;
1243                                          starty = currMV->y;                                          start_y = currMV->y;
1244                                  }                                  }
1245                          }                          }
1246                  }                  }
# Line 1148  Line 1258 
1258                                   const uint8_t * const cur,                                   const uint8_t * const cur,
1259                                   const int x,                                   const int x,
1260                                   const int y,                                   const int y,
1261                                   int32_t startx,                             const int start_x,
1262                                   int32_t starty,                             const int start_y,
1263                                   int32_t iMinSAD,                             int iMinSAD,
1264                                   VECTOR * const currMV,                                   VECTOR * const currMV,
1265                                   const VECTOR * const pmv,                             const int center_x,
1266                               const int center_y,
1267                                   const int32_t min_dx,                                   const int32_t min_dx,
1268                                   const int32_t max_dx,                                   const int32_t max_dx,
1269                                   const int32_t min_dy,                                   const int32_t min_dy,
# Line 1167  Line 1278 
1278          int32_t dx, dy;          int32_t dx, dy;
1279          VECTOR backupMV;          VECTOR backupMV;
1280    
1281          backupMV.x = startx;          backupMV.x = start_x;
1282          backupMV.y = starty;          backupMV.y = start_y;
1283    
1284          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1285                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
# Line 1177  Line 1288 
1288          return iMinSAD;          return iMinSAD;
1289  }  }
1290    
1291    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1292    
1293  int32_t  int32_t
1294  Halfpel16_Refine(const uint8_t * const pRef,  Halfpel16_Refine(const uint8_t * const pRef,
# Line 1189  Line 1300 
1300                                   const int y,                                   const int y,
1301                                   VECTOR * const currMV,                                   VECTOR * const currMV,
1302                                   int32_t iMinSAD,                                   int32_t iMinSAD,
1303                                   const VECTOR * const pmv,                             const int center_x,
1304                               const int center_y,
1305                                   const int32_t min_dx,                                   const int32_t min_dx,
1306                                   const int32_t max_dx,                                   const int32_t max_dx,
1307                                   const int32_t min_dy,                                   const int32_t min_dy,
# Line 1218  Line 1330 
1330  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1331    
1332    
1333    
1334  int32_t  int32_t
1335  PMVfastSearch16(const uint8_t * const pRef,  PMVfastSearch16(const uint8_t * const pRef,
1336                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
# Line 1226  Line 1339 
1339                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1340                                  const int x,                                  const int x,
1341                                  const int y,                                  const int y,
1342                                    const int start_x,      /* start is searched first, so it should contain the most */
1343                                    const int start_y,  /* likely motion vector for this block */
1344                                    const int center_x,     /* center is from where length of MVs is measured */
1345                                    const int center_y,
1346                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1347                                  const uint32_t iQuant,                                  const uint32_t iQuant,
1348                                  const uint32_t iFcode,                                  const uint32_t iFcode,
# Line 1259  Line 1376 
1376    
1377          MainSearch16FuncPtr MainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
1378    
 //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
1379          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1380    
1381          static int32_t threshA, threshB;          int32_t threshA, threshB;
1382          int32_t bPredEq;          int32_t bPredEq;
1383          int32_t iMinSAD, iSAD;          int32_t iMinSAD, iSAD;
1384    
# Line 1280  Line 1396 
1396          }          }
1397    
1398          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1399          bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1400    
1401          if ((x == 0) && (y == 0)) {          if ((x == 0) && (y == 0)) {
1402                  threshA = 512;                  threshA = 512;
1403                  threshB = 1024;                  threshB = 1024;
   
1404          } else {          } else {
1405                  threshA = psad[0];                  threshA = psad[0];
1406                  threshB = threshA + 256;                  threshB = threshA + 256;
# Line 1306  Line 1421 
1421     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1422  */  */
1423    
1424          *currMV = pmv[0];                       /* current best := prediction */          currMV->x = start_x;
1425            currMV->y = start_y;
1426    
1427          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
1428                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1429                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
# Line 1330  Line 1447 
1447                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1448                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1449          iMinSAD +=          iMinSAD +=
1450                  calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1451                                            (uint8_t) iFcode, iQuant);                                            (uint8_t) iFcode, iQuant);
1452    
1453          if ((iMinSAD < 256) ||          if ((iMinSAD < 256) ||
1454                  ((MVequal(*currMV, prevMB->mvs[0])) &&                  ((MVequal(*currMV, prevMB->mvs[0])) &&
1455                   ((uint32_t) iMinSAD < prevMB->sad16))) {                   ((int32_t) iMinSAD < prevMB->sad16))) {
1456                  if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode                  if (iMinSAD < (int)(2 * iQuant))        // high chances for SKIP-mode
1457                  {                  {
1458                          if (!MVzero(*currMV)) {                          if (!MVzero(*currMV)) {
1459                                  iMinSAD += MV16_00_BIAS;                                  iMinSAD += MV16_00_BIAS;
# Line 1439  Line 1556 
1556    
1557          if ((iMinSAD <= threshA) ||          if ((iMinSAD <= threshA) ||
1558                  (MVequal(*currMV, prevMB->mvs[0]) &&                  (MVequal(*currMV, prevMB->mvs[0]) &&
1559                   ((uint32_t) iMinSAD < prevMB->sad16))) {                   ((int32_t) iMinSAD < prevMB->sad16))) {
1560                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1561                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1562                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1466  Line 1583 
1583    
1584          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
1585    
1586    
1587  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1588          iSAD =          iSAD =
1589                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1590                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1591                                                      min_dx, max_dx,
1592                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1593                                                    iQuant, iFound);                                                    iQuant, iFound);
1594    
# Line 1484  Line 1603 
1603                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
1604                          iSAD =                          iSAD =
1605                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1606                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1607                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1608                                                                    iDiamondSize, iFcode, iQuant, iFound);                                                                    iDiamondSize, iFcode, iQuant, iFound);
1609    
# Line 1497  Line 1616 
1616                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1617                          iSAD =                          iSAD =
1618                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1619                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y,
1620                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                                    min_dx, max_dx, min_dy, max_dy,
1621                                                                      iEdgedWidth, iDiamondSize, iFcode,
1622                                                                    iQuant, iFound);                                                                    iQuant, iFound);
1623    
1624                          if (iSAD < iMinSAD) {                          if (iSAD < iMinSAD) {
# Line 1516  Line 1636 
1636          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
1637                  iMinSAD =                  iMinSAD =
1638                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1639                                                           iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1640                                                           iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1641    
1642    PMVfast16_Terminate_without_Refine:    PMVfast16_Terminate_without_Refine:
1643          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1644          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1645          return iMinSAD;          return iMinSAD;
1646  }  }
1647    
# Line 1538  Line 1658 
1658                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1659                                          const int x,                                          const int x,
1660                                          const int y,                                          const int y,
1661                                          int32_t startx,                                          const int32_t start_x,
1662                                          int32_t starty,                                          const int32_t start_y,
1663                                          int32_t iMinSAD,                                          int32_t iMinSAD,
1664                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1665                                          const VECTOR * const pmv,                                          const int center_x,
1666                                            const int center_y,
1667                                          const int32_t min_dx,                                          const int32_t min_dx,
1668                                          const int32_t max_dx,                                          const int32_t max_dx,
1669                                          const int32_t min_dy,                                          const int32_t min_dy,
# Line 1556  Line 1677 
1677  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1678    
1679          int32_t iDirection = 0;          int32_t iDirection = 0;
1680            int32_t iDirectionBackup;
1681          int32_t iSAD;          int32_t iSAD;
1682          VECTOR backupMV;          VECTOR backupMV;
1683    
1684          backupMV.x = startx;          backupMV.x = start_x;
1685          backupMV.y = starty;          backupMV.y = start_y;
1686    
1687  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1688    
# Line 1569  Line 1691 
1691          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1692          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1693    
1694          if (iDirection)          if (iDirection) {
1695                  while (!iFound) {                  while (!iFound) {
1696                          iFound = 1;                          iFound = 1;
1697                          backupMV = *currMV;     // since iDirection!=0, this is well defined!                          backupMV = *currMV;     // since iDirection!=0, this is well defined!
1698                            iDirectionBackup = iDirection;
1699    
1700                            if (iDirectionBackup != 2)
1701                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1702                                                                                      backupMV.y, 1);
1703                            if (iDirectionBackup != 1)
1704                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1705                                                                                      backupMV.y, 2);
1706                            if (iDirectionBackup != 4)
1707                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1708                                                                                      backupMV.y - iDiamondSize, 3);
1709                            if (iDirectionBackup != 3)
1710                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1711                                                                                      backupMV.y + iDiamondSize, 4);
1712                    }
1713            } else {
1714                    currMV->x = start_x;
1715                    currMV->y = start_y;
1716            }
1717            return iMinSAD;
1718    }
1719    
1720    
1721    
1722    
1723    int32_t
1724    Square8_MainSearch(const uint8_t * const pRef,
1725                                       const uint8_t * const pRefH,
1726                                       const uint8_t * const pRefV,
1727                                       const uint8_t * const pRefHV,
1728                                       const uint8_t * const cur,
1729                                       const int x,
1730                                       const int y,
1731                                       const int32_t start_x,
1732                                       const int32_t start_y,
1733                                       int32_t iMinSAD,
1734                                       VECTOR * const currMV,
1735                                       const int center_x,
1736                                       const int center_y,
1737                                       const int32_t min_dx,
1738                                       const int32_t max_dx,
1739                                       const int32_t min_dy,
1740                                       const int32_t max_dy,
1741                                       const int32_t iEdgedWidth,
1742                                       const int32_t iDiamondSize,
1743                                       const int32_t iFcode,
1744                                       const int32_t iQuant,
1745                                       int iFound)
1746    {
1747    /* Do a square search around given starting point, return SAD of best */
1748    
1749                          if (iDirection != 2)          int32_t iDirection = 0;
1750            int32_t iSAD;
1751            VECTOR backupMV;
1752    
1753            backupMV.x = start_x;
1754            backupMV.y = start_y;
1755    
1756    /* It's one search with full square pattern, and new parts for all following diamonds */
1757    
1758    /*   new direction are extra, so 1-4 is normal diamond
1759          537
1760          1*2
1761          648
1762    */
1763    
1764            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1765            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1766            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1767            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1768    
1769            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1770                                                             backupMV.y - iDiamondSize, 5);
1771            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1772                                                             backupMV.y + iDiamondSize, 6);
1773            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1774                                                             backupMV.y - iDiamondSize, 7);
1775            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1776                                                             backupMV.y + iDiamondSize, 8);
1777    
1778    
1779            if (iDirection) {
1780                    while (!iFound) {
1781                            iFound = 1;
1782                            backupMV = *currMV;
1783    
1784                            switch (iDirection) {
1785                            case 1:
1786                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1787                                                                                       backupMV.y, 1);
1788                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1789                                                                                     backupMV.y - iDiamondSize, 5);
1790                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1791                                                                                     backupMV.y - iDiamondSize, 7);
1792                                    break;
1793                            case 2:
1794                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1795                                                                                     2);
1796                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1797                                                                                     backupMV.y + iDiamondSize, 6);
1798                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1799                                                                                     backupMV.y + iDiamondSize, 8);
1800                                    break;
1801    
1802                            case 3:
1803                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1804                                                                                     4);
1805                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1806                                                                                     backupMV.y - iDiamondSize, 7);
1807                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1808                                                                                     backupMV.y + iDiamondSize, 8);
1809                                    break;
1810    
1811                            case 4:
1812                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1813                                                                                     3);
1814                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1815                                                                                     backupMV.y - iDiamondSize, 5);
1816                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1817                                                                                     backupMV.y + iDiamondSize, 6);
1818                                    break;
1819    
1820                            case 5:
1821                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1822                                                                                     1);
1823                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1824                                                                                     3);
1825                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1826                                                                                     backupMV.y - iDiamondSize, 5);
1827                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1828                                                                                     backupMV.y + iDiamondSize, 6);
1829                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1830                                                                                     backupMV.y - iDiamondSize, 7);
1831                                    break;
1832    
1833                            case 6:
1834                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1835                                                                                     2);
1836                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1837                                                                                     3);
1838    
1839                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1840                                                                                     backupMV.y - iDiamondSize, 5);
1841                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1842                                                                                     backupMV.y + iDiamondSize, 6);
1843                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1844                                                                                     backupMV.y + iDiamondSize, 8);
1845    
1846                                    break;
1847    
1848                            case 7:
1849                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1850                                                                                    backupMV.y, 1);                                                                                    backupMV.y, 1);
1851                          if (iDirection != 1)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1852                                                                                     4);
1853                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1854                                                                                     backupMV.y - iDiamondSize, 5);
1855                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1856                                                                                     backupMV.y - iDiamondSize, 7);
1857                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1858                                                                                     backupMV.y + iDiamondSize, 8);
1859                                    break;
1860    
1861                            case 8:
1862                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1863                                                                                     2);
1864                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1865                                                                                     4);
1866                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1867                                                                                     backupMV.y + iDiamondSize, 6);
1868                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1869                                                                                     backupMV.y - iDiamondSize, 7);
1870                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1871                                                                                     backupMV.y + iDiamondSize, 8);
1872                                    break;
1873                            default:
1874                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1875                                                                                     1);
1876                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1877                                                                                     2);
1878                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1879                                                                                     3);
1880                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1881                                                                                     4);
1882    
1883                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1884                                                                                     backupMV.y - iDiamondSize, 5);
1885                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1886                                                                                     backupMV.y + iDiamondSize, 6);
1887                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1888                                                                                     backupMV.y - iDiamondSize, 7);
1889                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1890                                                                                    backupMV.y, 2);                                                                                   backupMV.y + iDiamondSize, 8);
1891                          if (iDirection != 4)                                  break;
1892                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,                          }
1893                                                                                    backupMV.y - iDiamondSize, 3);                  }
                         if (iDirection != 3)  
                                 CHECK_MV8_CANDIDATE_FOUND(backupMV.x,  
                                                                                   backupMV.y + iDiamondSize, 4);  
1894          } else {          } else {
1895                  currMV->x = startx;                  currMV->x = start_x;
1896                  currMV->y = starty;                  currMV->y = start_y;
1897          }          }
1898          return iMinSAD;          return iMinSAD;
1899  }  }
1900    
1901    
1902    
1903    
1904    
1905  int32_t  int32_t
1906  Halfpel8_Refine(const uint8_t * const pRef,  Halfpel8_Refine_c(const uint8_t * const pRef,
1907                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
1908                                  const uint8_t * const pRefV,                                  const uint8_t * const pRefV,
1909                                  const uint8_t * const pRefHV,                                  const uint8_t * const pRefHV,
# Line 1603  Line 1912 
1912                                  const int y,                                  const int y,
1913                                  VECTOR * const currMV,                                  VECTOR * const currMV,
1914                                  int32_t iMinSAD,                                  int32_t iMinSAD,
1915                                  const VECTOR * const pmv,                                    const int center_x,
1916                                      const int center_y,
1917                                  const int32_t min_dx,                                  const int32_t min_dx,
1918                                  const int32_t max_dx,                                  const int32_t max_dx,
1919                                  const int32_t min_dy,                                  const int32_t min_dy,
# Line 1642  Line 1952 
1952                             const int y,                             const int y,
1953                             const int start_x,                             const int start_x,
1954                             const int start_y,                             const int start_y,
1955                                    const int center_x,
1956                                    const int center_y,
1957                             const uint32_t MotionFlags,                             const uint32_t MotionFlags,
1958                             const uint32_t iQuant,                             const uint32_t iQuant,
1959                             const uint32_t iFcode,                             const uint32_t iFcode,
# Line 1674  Line 1986 
1986  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1987          const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;          const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
1988    
1989          static int32_t threshA, threshB;           int32_t threshA, threshB;
1990          int32_t iFound, bPredEq;          int32_t iFound, bPredEq;
1991          int32_t iMinSAD, iSAD;          int32_t iMinSAD, iSAD;
1992    
# Line 1698  Line 2010 
2010          }          }
2011    
2012          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
2013          bPredEq =          bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
                 get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);  
2014    
2015          if ((x == 0) && (y == 0)) {          if ((x == 0) && (y == 0)) {
2016                  threshA = 512 / 4;                  threshA = 512 / 4;
2017                  threshB = 1024 / 4;                  threshB = 1024 / 4;
2018    
2019          } else {          } else {
2020                  threshA = psad[0] / 4;  /* good estimate */                  threshA = psad[0] / 4;  /* good estimate? */
2021                  threshB = threshA + 256 / 4;                  threshB = threshA + 256 / 4;
2022                  if (threshA < 512 / 4)                  if (threshA < 512 / 4)
2023                          threshA = 512 / 4;                          threshA = 512 / 4;
# Line 1728  Line 2039 
2039    
2040  // Prepare for main loop  // Prepare for main loop
2041    
2042  //  if (MotionFlags & PMV_USESQUARES8)    if (MotionFlags & PMV_USESQUARES8)
2043  //      MainSearchPtr = Square8_MainSearch;        MainSearchPtr = Square8_MainSearch;
2044  //  else    else
2045    
2046          if (MotionFlags & PMV_ADVANCEDDIAMOND8)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2047                  MainSearchPtr = AdvDiamond8_MainSearch;                  MainSearchPtr = AdvDiamond8_MainSearch;
# Line 1745  Line 2056 
2056                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2057                                                  iEdgedWidth), iEdgedWidth);                                                  iEdgedWidth), iEdgedWidth);
2058          iMinSAD +=          iMinSAD +=
2059                  calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2060                                           (uint8_t) iFcode, iQuant);                                           (uint8_t) iFcode, iQuant);
2061    
2062          if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))          if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
2063                                                                  && ((uint32_t) iMinSAD <                                                                  && ((int32_t) iMinSAD <
2064                                                                          prevMB->sad8[iSubBlock]))) {                                                                          prevMB->sad8[iSubBlock]))) {
2065                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2066                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
# Line 1788  Line 2099 
2099  // the median prediction might be even better than mv16  // the median prediction might be even better than mv16
2100    
2101          if (!MVequal(pmv[0], startMV))          if (!MVequal(pmv[0], startMV))
2102                  CHECK_MV8_CANDIDATE(pmv[0].x, pmv[0].y);                  CHECK_MV8_CANDIDATE(center_x, center_y);
2103    
2104  // (0,0) if needed  // (0,0) if needed
2105          if (!MVzero(pmv[0]))          if (!MVzero(pmv[0]))
# Line 1804  Line 2115 
2115    
2116          if ((iMinSAD <= threshA) ||          if ((iMinSAD <= threshA) ||
2117                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2118                   ((uint32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {                   ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2119                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2120                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2121                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1863  Line 2174 
2174    
2175          if ((iMinSAD <= threshA) ||          if ((iMinSAD <= threshA) ||
2176                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2177                   ((uint32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {                   ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2178                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2179                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2180                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1885  Line 2196 
2196  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2197          iSAD =          iSAD =
2198                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2199                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2200                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2201                                                    iQuant, iFound);                                                    iQuant, iFound);
2202    
# Line 1900  Line 2211 
2211                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
2212                          iSAD =                          iSAD =
2213                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2214                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2215                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2216                                                                    iDiamondSize, iFcode, iQuant, iFound);                                                                    iDiamondSize, iFcode, iQuant, iFound);
2217    
# Line 1913  Line 2224 
2224                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2225                          iSAD =                          iSAD =
2226                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2227                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2228                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2229                                                                    iQuant, iFound);                                                                    iQuant, iFound);
2230    
# Line 1932  Line 2243 
2243          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2244                  iMinSAD =                  iMinSAD =
2245                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2246                                                          iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2247                                                          iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2248    
2249    
2250    PMVfast8_Terminate_without_Refine:    PMVfast8_Terminate_without_Refine:
2251          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2252          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2253    
2254          return iMinSAD;          return iMinSAD;
2255  }  }
# Line 1951  Line 2262 
2262                           const IMAGE * const pCur,                           const IMAGE * const pCur,
2263                           const int x,                           const int x,
2264                           const int y,                           const int y,
2265                            const int start_x,
2266                            const int start_y,
2267                            const int center_x,
2268                            const int center_y,
2269                           const uint32_t MotionFlags,                           const uint32_t MotionFlags,
2270                           const uint32_t iQuant,                           const uint32_t iQuant,
2271                           const uint32_t iFcode,                           const uint32_t iFcode,
# Line 1986  Line 2301 
2301          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2302          MACROBLOCK *oldMB = NULL;          MACROBLOCK *oldMB = NULL;
2303    
2304          static int32_t thresh2;           int32_t thresh2;
2305          int32_t bPredEq;          int32_t bPredEq;
2306          int32_t iMinSAD, iSAD = 9999;          int32_t iMinSAD, iSAD = 9999;
2307    
# Line 2009  Line 2324 
2324                  max_dy = EVEN(max_dy);                  max_dy = EVEN(max_dy);
2325          }          }
2326          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2327          bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2328    
2329  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2330          MinSAD=SAD          MinSAD=SAD
# Line 2020  Line 2335 
2335    
2336  // Prepare for main loop  // Prepare for main loop
2337    
2338          *currMV = pmv[0];                       /* current best := median prediction */          currMV->x = start_x;
2339            currMV->y = start_y;
2340    
2341          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
2342                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2343                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
# Line 2042  Line 2359 
2359                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2360                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2361          iMinSAD +=          iMinSAD +=
2362                  calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2363                                            (uint8_t) iFcode, iQuant);                                            (uint8_t) iFcode, iQuant);
2364    
2365  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2366          if ((iMinSAD < 256) ||          if ((iMinSAD < 256) ||
2367                  ((MVequal(*currMV, prevMB->mvs[0])) &&                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2368                   ((uint32_t) iMinSAD < prevMB->sad16))) {                   ((int32_t) iMinSAD < prevMB->sad16))) {
2369                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2370                          goto EPZS16_Terminate_without_Refine;                          goto EPZS16_Terminate_without_Refine;
2371                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 2108  Line 2425 
2425    
2426          if ((iMinSAD <= thresh2)          if ((iMinSAD <= thresh2)
2427                  || (MVequal(*currMV, prevMB->mvs[0]) &&                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2428                          ((uint32_t) iMinSAD <= prevMB->sad16))) {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2429                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2430                          goto EPZS16_Terminate_without_Refine;                          goto EPZS16_Terminate_without_Refine;
2431                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 2154  Line 2471 
2471    
2472          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2473    
2474          if (MotionFlags & PMV_USESQUARES8)          if (MotionFlags & PMV_USESQUARES16)
2475                  MainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
2476          else          else
2477           if (MotionFlags & PMV_ADVANCEDDIAMOND8)           if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2478                  MainSearchPtr = AdvDiamond16_MainSearch;                  MainSearchPtr = AdvDiamond16_MainSearch;
2479          else          else
2480                  MainSearchPtr = Diamond16_MainSearch;                  MainSearchPtr = Diamond16_MainSearch;
# Line 2166  Line 2483 
2483    
2484          iSAD =          iSAD =
2485                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2486                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2487                                                    min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                    min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2488    
2489          if (iSAD < iMinSAD) {          if (iSAD < iMinSAD) {
# Line 2181  Line 2498 
2498                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
2499                          iSAD =                          iSAD =
2500                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2501                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2502                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2503                                                                    2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2504                  }                  }
# Line 2194  Line 2511 
2511                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2512                          iSAD =                          iSAD =
2513                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2514                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2515                                                                    max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2516    
2517                          if (iSAD < iMinSAD) {                          if (iSAD < iMinSAD) {
# Line 2210  Line 2527 
2527          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2528                  iMinSAD =                  iMinSAD =
2529                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2530                                                           iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2531                                                           iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
2532    
2533    EPZS16_Terminate_without_Refine:    EPZS16_Terminate_without_Refine:
2534    
2535          *oldMB = *prevMB;          *oldMB = *prevMB;
2536    
2537          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2538          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2539          return iMinSAD;          return iMinSAD;
2540  }  }
2541    
# Line 2233  Line 2550 
2550                          const int y,                          const int y,
2551                          const int start_x,                          const int start_x,
2552                          const int start_y,                          const int start_y,
2553                            const int center_x,
2554                            const int center_y,
2555                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
2556                          const uint32_t iQuant,                          const uint32_t iQuant,
2557                          const uint32_t iFcode,                          const uint32_t iFcode,
# Line 2287  Line 2606 
2606                  max_dy = EVEN(max_dy);                  max_dy = EVEN(max_dy);
2607          }          }
2608          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2609          bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2610    
2611    
2612  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 2322  Line 2641 
2641                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2642                                                  iEdgedWidth), iEdgedWidth);                                                  iEdgedWidth), iEdgedWidth);
2643          iMinSAD +=          iMinSAD +=
2644                  calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2645                                           (uint8_t) iFcode, iQuant);                                           (uint8_t) iFcode, iQuant);
2646    
2647    
# Line 2398  Line 2717 
2717    
2718  // there is no EPZS^2 for inter4v at the moment  // there is no EPZS^2 for inter4v at the moment
2719    
2720  //  if (MotionFlags & PMV_USESQUARES8)    if (MotionFlags & PMV_USESQUARES8)
2721  //      MainSearchPtr = Square8_MainSearch;        MainSearchPtr = Square8_MainSearch;
2722  //  else    else
2723    
2724          if (MotionFlags & PMV_ADVANCEDDIAMOND8)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2725                  MainSearchPtr = AdvDiamond8_MainSearch;                  MainSearchPtr = AdvDiamond8_MainSearch;
# Line 2409  Line 2728 
2728    
2729          iSAD =          iSAD =
2730                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2731                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2732                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2733                                                    iQuant, 0);                                                    iQuant, 0);
2734    
# Line 2425  Line 2744 
2744                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
2745                          iSAD =                          iSAD =
2746                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2747                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2748                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2749                                                                    iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2750    
# Line 2438  Line 2757 
2757                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2758                          iSAD =                          iSAD =
2759                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2760                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2761                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2762                                                                    iQuant, 0);                                                                    iQuant, 0);
2763    
# Line 2455  Line 2774 
2774          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2775                  iMinSAD =                  iMinSAD =
2776                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2777                                                          iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2778                                                          iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2779    
2780    EPZS8_Terminate_without_Refine:    EPZS8_Terminate_without_Refine:
2781    
2782          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2783          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2784          return iMinSAD;          return iMinSAD;
2785  }  }
2786    
2787    
2788    
2789    int32_t
2790    PMVfastIntSearch16(const uint8_t * const pRef,
2791                                    const uint8_t * const pRefH,
2792                                    const uint8_t * const pRefV,
2793                                    const uint8_t * const pRefHV,
2794                                    const IMAGE * const pCur,
2795                                    const int x,
2796                                    const int y,
2797                                    const int start_x,              /* start should be most likely vector */
2798                                    const int start_y,
2799                                    const int center_x,             /* center is from where length of MVs is measured */
2800                                    const int center_y,
2801                                    const uint32_t MotionFlags,
2802                                    const uint32_t iQuant,
2803                                    const uint32_t iFcode,
2804                                    const MBParam * const pParam,
2805                                    const MACROBLOCK * const pMBs,
2806                                    const MACROBLOCK * const prevMBs,
2807                                    VECTOR * const currMV,
2808                                    VECTOR * const currPMV)
2809    {
2810            const uint32_t iWcount = pParam->mb_width;
2811            const int32_t iWidth = pParam->width;
2812            const int32_t iHeight = pParam->height;
2813            const int32_t iEdgedWidth = pParam->edged_width;
2814    
2815            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2816            const VECTOR zeroMV = { 0, 0 };
2817    
2818            int32_t iDiamondSize;
2819    
2820            int32_t min_dx;
2821            int32_t max_dx;
2822            int32_t min_dy;
2823            int32_t max_dy;
2824    
2825            int32_t iFound;
2826    
2827            VECTOR newMV;
2828            VECTOR backupMV;
2829    
2830            VECTOR pmv[4];
2831            int32_t psad[4];
2832    
2833  /* ***********************************************************          MainSearch16FuncPtr MainSearchPtr;
2834          bvop motion estimation  
2835  // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)          MACROBLOCK *const prevMB = (MACROBLOCK *const)prevMBs + x + y * iWcount;
2836  ***************************************************************/          MACROBLOCK *const pMB = (MACROBLOCK *const)(pMBs + x + y * iWcount);
2837    
2838            int32_t threshA, threshB;
2839  void          int32_t bPredEq;
2840  MotionEstimationBVOP(MBParam * const pParam,          int32_t iMinSAD, iSAD;
2841                                           FRAMEINFO * const frame,  
2842                                           // forward (past) reference  
2843                                           const MACROBLOCK * const f_mbs,  /* Get maximum range */
2844                                           const IMAGE * const f_ref,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2845                                           const IMAGE * const f_refH,                            iFcode);
2846                                           const IMAGE * const f_refV,  
2847                                           const IMAGE * const f_refHV,  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2848                                           // backward (future) reference  
2849                                           const MACROBLOCK * const b_mbs,          if ((x == 0) && (y == 0)) {
2850                                           const IMAGE * const b_ref,                  threshA = 512;
2851                                           const IMAGE * const b_refH,                  threshB = 1024;
2852                                           const IMAGE * const b_refV,  
2853                                           const IMAGE * const b_refHV)                  bPredEq = 0;
2854  {                  psad[0] = psad[1] = psad[2] = psad[3] = 0;
2855          const uint32_t mb_width = pParam->mb_width;                  *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
         const uint32_t mb_height = pParam->mb_height;  
         const int32_t edged_width = pParam->edged_width;  
   
         uint32_t i, j;  
   
         int32_t f_sad16;  
         int32_t b_sad16;  
         int32_t i_sad16;  
         int32_t d_sad16;  
         int32_t best_sad;  
   
         VECTOR pmv_dontcare;  
   
         // note: i==horizontal, j==vertical  
         for (j = 0; j < mb_height; j++) {  
                 for (i = 0; i < mb_width; i++) {  
                         MACROBLOCK *mb = &frame->mbs[i + j * mb_width];  
                         const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width];  
                         const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width];  
   
                         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;  
                         }  
2856    
                         // forward search  
                         f_sad16 =  
                                 SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,  
                                                  &frame->image, i, j, frame->motion_flags,  
                                                  frame->quant, frame->fcode, pParam, f_mbs,  
                                                  f_mbs /* todo */ ,  
                                                  &mb->mvs[0], &pmv_dontcare);   // ignore pmv  
   
                         // backward search  
                         b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y, &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;  
   
   
                         if (f_sad16 < b_sad16) {  
                                 best_sad = f_sad16;  
                                 mb->mode = MODE_FORWARD;  
2857                          } else {                          } else {
2858                                  best_sad = b_sad16;  
2859                                  mb->mode = MODE_BACKWARD;                  bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2860    
2861                    threshA = psad[0];
2862                    threshB = threshA + 256;
2863                    if (threshA < 512)
2864                            threshA = 512;
2865                    if (threshA > 1024)
2866                            threshA = 1024;
2867                    if (threshB > 1792)
2868                            threshB = 1792;
2869    
2870                    *currMV = pmv[0];                       /* current best := prediction */
2871            }
2872    
2873            iFound = 0;
2874    
2875    /* Step 4: Calculate SAD around the Median prediction.
2876       MinSAD=SAD
2877       If Motion Vector equal to Previous frame motion vector
2878       and MinSAD<PrevFrmSAD goto Step 10.
2879       If SAD<=256 goto Step 10.
2880    */
2881    
2882            if (currMV->x > max_dx) {
2883                    currMV->x = EVEN(max_dx);
2884            }
2885            if (currMV->x < min_dx) {
2886                    currMV->x = EVEN(min_dx);
2887            }
2888            if (currMV->y > max_dy) {
2889                    currMV->y = EVEN(max_dy);
2890            }
2891            if (currMV->y < min_dy) {
2892                    currMV->y = EVEN(min_dy);
2893            }
2894    
2895            iMinSAD =
2896                    sad16(cur,
2897                              get_iref_mv(pRef, x, y, 16, currMV,
2898                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2899            iMinSAD +=
2900                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2901                                              (uint8_t) iFcode, iQuant);
2902    
2903            if ((iMinSAD < 256) ||
2904                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2905                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2906                    if (iMinSAD < (int)(2 * iQuant))        // high chances for SKIP-mode
2907                    {
2908                            if (!MVzero(*currMV)) {
2909                                    iMinSAD += MV16_00_BIAS;
2910                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2911                                    iMinSAD -= MV16_00_BIAS;
2912                            }
2913                    }
2914    
2915                    if (MotionFlags & PMV_EARLYSTOP16)
2916                            goto PMVfastInt16_Terminate_with_Refine;
2917                          }                          }
2918    
2919                          if (i_sad16 < best_sad) {  
2920                                  best_sad = i_sad16;  /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2921                                  mb->mode = MODE_INTERPOLATE;     vector of the median.
2922       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2923    */
2924    
2925            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2926                    iFound = 2;
2927    
2928    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2929       Otherwise select large Diamond Search.
2930    */
2931    
2932            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2933                    iDiamondSize = 2;               // halfpel units!
2934            else
2935                    iDiamondSize = 4;               // halfpel units!
2936    
2937    /*
2938       Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2939       Also calculate (0,0) but do not subtract offset.
2940       Let MinSAD be the smallest SAD up to this point.
2941       If MV is (0,0) subtract offset.
2942    */
2943    
2944    // (0,0) is often a good choice
2945    
2946            if (!MVzero(pmv[0]))
2947                    CHECK_MV16_ZERO;
2948    
2949    // previous frame MV is always possible
2950    
2951            if (!MVzero(prevMB->i_mvs[0]))
2952                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2953                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2954    
2955    // left neighbour, if allowed
2956    
2957            if (!MVzero(pmv[1]))
2958                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2959                            if (!MVequal(pmv[1], pmv[0]))
2960                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2961    
2962    // top neighbour, if allowed
2963            if (!MVzero(pmv[2]))
2964                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
2965                            if (!MVequal(pmv[2], pmv[0]))
2966                                    if (!MVequal(pmv[2], pmv[1]))
2967                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2968    
2969    // top right neighbour, if allowed
2970                                            if (!MVzero(pmv[3]))
2971                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
2972                                                            if (!MVequal(pmv[3], pmv[0]))
2973                                                                    if (!MVequal(pmv[3], pmv[1]))
2974                                                                            if (!MVequal(pmv[3], pmv[2]))
2975                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
2976                                                                                                                             pmv[3].y);
2977    
2978            if ((MVzero(*currMV)) &&
2979                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2980                    iMinSAD -= MV16_00_BIAS;
2981    
2982    
2983    /* Step 6: If MinSAD <= thresa goto Step 10.
2984       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2985    */
2986    
2987            if ((iMinSAD <= threshA) ||
2988                    (MVequal(*currMV, prevMB->i_mvs[0]) &&
2989                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2990    
2991                    if (MotionFlags & PMV_EARLYSTOP16)
2992                            goto PMVfastInt16_Terminate_with_Refine;
2993            }
2994    
2995    
2996    /************ (Diamond Search)  **************/
2997    /*
2998       Step 7: Perform Diamond search, with either the small or large diamond.
2999       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
3000       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
3001       If center then goto step 10.
3002       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
3003       Refine by using small diamond and goto step 10.
3004    */
3005    
3006            if (MotionFlags & PMV_USESQUARES16)
3007                    MainSearchPtr = Square16_MainSearch;
3008            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
3009                    MainSearchPtr = AdvDiamond16_MainSearch;
3010            else
3011                    MainSearchPtr = Diamond16_MainSearch;
3012    
3013            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
3014    
3015    
3016    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
3017            iSAD =
3018                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
3019                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
3020                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
3021                                                      iQuant, iFound);
3022    
3023            if (iSAD < iMinSAD) {
3024                    *currMV = newMV;
3025                    iMinSAD = iSAD;
3026                          }                          }
3027    
3028                          if (d_sad16 < best_sad) {          if (MotionFlags & PMV_EXTSEARCH16) {
3029                                  best_sad = d_sad16;  /* extended: search (up to) two more times: orignal prediction and (0,0) */
3030                                  mb->mode = MODE_DIRECT;  
3031                    if (!(MVequal(pmv[0], backupMV))) {
3032                            iSAD =
3033                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
3034                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
3035                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
3036                                                                      iDiamondSize, iFcode, iQuant, iFound);
3037    
3038                            if (iSAD < iMinSAD) {
3039                                    *currMV = newMV;
3040                                    iMinSAD = iSAD;
3041                          }                          }
3042                    }
3043    
3044                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
3045                            iSAD =
3046                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
3047                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
3048                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
3049                                                                      iQuant, iFound);
3050    
3051                            if (iSAD < iMinSAD) {
3052                                    *currMV = newMV;
3053                                    iMinSAD = iSAD;
3054                  }                  }
3055          }          }
3056  }  }
3057    
3058    /*
3059       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
3060    */
3061    
3062    PMVfastInt16_Terminate_with_Refine:
3063    
3064            pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
3065            pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
3066    
3067            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
3068                    iMinSAD =
3069                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
3070                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
3071                                                             iFcode, iQuant, iEdgedWidth);
3072    
3073            pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
3074    
3075            currPMV->x = currMV->x - center_x;
3076            currPMV->y = currMV->y - center_y;
3077            return iMinSAD;
3078    }
3079    

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

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