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

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

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