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

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

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