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

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

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