[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 252, Sun Jun 30 10:46:29 2002 UTC revision 430, Fri Sep 6 16:59:47 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>
9   *  14.04.2002 added MotionEstimationBVOP()   *  Copyright(C) 2002 chenm001 <chenm001@163.com>
  *  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.  
10   *   *
11   *  Michael Militzer <isibaar@videocoding.de>   *  This program is an implementation of a part of one or more MPEG-4
12     *  Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
13     *  to use this software module in hardware or software products are
14     *  advised that its use may infringe existing patents or copyrights, and
15     *  any such use would be at such party's own risk.  The original
16     *  developer of this software module and his/her company, and subsequent
17     *  editors and their companies, will have no liability for use of this
18     *  software or modifications or derivatives thereof.
19   *   *
20   **************************************************************************/   *  This program is free software; you can redistribute it and/or modify
21     *  it under the terms of the GNU General Public License as published by
22     *  the Free Software Foundation; either version 2 of the License, or
23     *  (at your option) any later version.
24     *
25     *  This program is distributed in the hope that it will be useful,
26     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
27     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28     *  GNU General Public License for more details.
29     *
30     *  You should have received a copy of the GNU General Public License
31     *  along with this program; if not, write to the Free Software
32     *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
33     *
34     *************************************************************************/
35    
36  #include <assert.h>  #include <assert.h>
37  #include <stdio.h>  #include <stdio.h>
# Line 47  Line 45 
45  #include "motion.h"  #include "motion.h"
46  #include "sad.h"  #include "sad.h"
47    
 // very large value  
 #define MV_MAX_ERROR    (4096 * 256)  
   
 // stop search if sdelta < THRESHOLD  
 #define MV16_THRESHOLD  192  
 #define MV8_THRESHOLD   56  
   
 #define NEIGH_MOVE_THRESH 0  
 // how much a block's MV must differ from his neighbour  
 // to be search for INTER4V. The more, the faster...  
   
 /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  
 /* nb  = vop pixels * 2^(bpp-8) */  
 #define MV16_00_BIAS    (128+1)  
 #define MV8_00_BIAS     (0)  
   
 /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */  
 #define MV16_INTER_BIAS 512  
   
 /* Parameters which control inter/inter4v decision */  
 #define IMV16X16                        5  
   
 /* vector map (vlc delta size) smoother parameters */  
 #define NEIGH_TEND_16X16        2  
 #define NEIGH_TEND_8X8          2  
   
 // fast ((A)/2)*2  
 #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  
   
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
 int32_t PMVfastSearch16(const uint8_t * const pRef,  
                                                 const uint8_t * const pRefH,  
                                                 const uint8_t * const pRefV,  
                                                 const uint8_t * const pRefHV,  
                                                 const IMAGE * const pCur,  
                                                 const int x,  
                                                 const int y,  
                                                 const uint32_t MotionFlags,  
                                                 const uint32_t iQuant,  
                                                 const uint32_t iFcode,  
                                                 const MBParam * const pParam,  
                                                 const MACROBLOCK * const pMBs,  
                                                 const MACROBLOCK * const prevMBs,  
                                                 VECTOR * const currMV,  
                                                 VECTOR * const currPMV);  
   
 int32_t EPZSSearch16(const uint8_t * const pRef,  
                                          const uint8_t * const pRefH,  
                                          const uint8_t * const pRefV,  
                                          const uint8_t * const pRefHV,  
                                          const IMAGE * const pCur,  
                                          const int x,  
                                          const int y,  
                                          const uint32_t MotionFlags,  
                                          const uint32_t iQuant,  
                                          const uint32_t iFcode,  
                                          const MBParam * const pParam,  
                                          const MACROBLOCK * const pMBs,  
                                          const MACROBLOCK * const prevMBs,  
                                          VECTOR * const currMV,  
                                          VECTOR * const currPMV);  
   
   
 int32_t PMVfastSearch8(const uint8_t * const pRef,  
                                            const uint8_t * const pRefH,  
                                            const uint8_t * const pRefV,  
                                            const uint8_t * const pRefHV,  
                                            const IMAGE * const pCur,  
                                            const int x,  
                                            const int y,  
                                            const int start_x,  
                                            const int start_y,  
                                            const uint32_t MotionFlags,  
                                            const uint32_t iQuant,  
                                            const uint32_t iFcode,  
                                            const MBParam * const pParam,  
                                            const MACROBLOCK * const pMBs,  
                                            const MACROBLOCK * const prevMBs,  
                                            VECTOR * const currMV,  
                                            VECTOR * const currPMV);  
   
 int32_t EPZSSearch8(const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x,  
                                         const int y,  
                                         const int start_x,  
                                         const int start_y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
   
 typedef int32_t(MainSearch16Func) (const uint8_t * const pRef,  
                                                                    const uint8_t * const pRefH,  
                                                                    const uint8_t * const pRefV,  
                                                                    const uint8_t * const pRefHV,  
                                                                    const uint8_t * const cur,  
                                                                    const int x,  
                                                                    const int y,  
                                                                    int32_t startx,  
                                                                    int32_t starty,  
                                                                    int32_t iMinSAD,  
                                                                    VECTOR * const currMV,  
                                                                    const VECTOR * const pmv,  
                                                                    const int32_t min_dx,  
                                                                    const int32_t max_dx,  
                                                                    const int32_t min_dy,  
                                                                    const int32_t max_dy,  
                                                                    const int32_t iEdgedWidth,  
                                                                    const int32_t iDiamondSize,  
                                                                    const int32_t iFcode,  
                                                                    const int32_t iQuant,  
                                                                    int iFound);  
   
 typedef MainSearch16Func *MainSearch16FuncPtr;  
   
   
 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);  
48    
 typedef MainSearch8Func *MainSearch8FuncPtr;  
49    
50  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 */
51  { 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 123 
123                                                                                                     mv_bits(dy, iFcode));                                                                                                     mv_bits(dy, iFcode));
124  }  }
125    
   
   
   
   
 #ifndef SEARCH16  
 #define SEARCH16        PMVfastSearch16  
 //#define SEARCH16  FullSearch16  
 //#define SEARCH16  EPZSSearch16  
 #endif  
   
 #ifndef SEARCH8  
 #define SEARCH8         PMVfastSearch8  
 //#define SEARCH8   EPZSSearch8  
 #endif  
   
126  bool  bool
127  MotionEstimation(MBParam * const pParam,  MotionEstimation(MBParam * const pParam,
128                                   FRAMEINFO * const current,                                   FRAMEINFO * const current,
# Line 305  Line 139 
139          const IMAGE *const pCurrent = &current->image;          const IMAGE *const pCurrent = &current->image;
140          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
141    
142          const VECTOR zeroMV = { 0, 0 };          static const VECTOR zeroMV = { 0, 0 };
143            VECTOR predMV;
144    
145          int32_t x, y;          int32_t x, y;
146          int32_t iIntra = 0;          int32_t iIntra = 0;
# Line 314  Line 149 
149          if (sadInit)          if (sadInit)
150                  (*sadInit) ();                  (*sadInit) ();
151    
152          for (y = 0; y < iHcount; y++)          for (y = 0; y < iHcount; y++)   {
153                  for (x = 0; x < iWcount; x++) {                  for (x = 0; x < iWcount; x++) {
154    
155                          MACROBLOCK *const pMB = &pMBs[x + y * iWcount];                          MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
156    
157                            if (pMB->mode == MODE_NOT_CODED)
158                                    continue;
159    
160                            predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
161    
162                          pMB->sad16 =                          pMB->sad16 =
163                                  SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                                  SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
164                                                   y, current->motion_flags, current->quant,                                                   x, y, predMV.x, predMV.y, predMV.x, predMV.y,
165                                                     current->motion_flags, current->quant,
166                                                   current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,                                                   current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
167                                                   &pMB->pmvs[0]);                                                   &pMB->pmvs[0]);
168    
# Line 352  Line 194 
194                                           pMB->dquant == NO_CHANGE)) {                                           pMB->dquant == NO_CHANGE)) {
195                                          int32_t sad8 = IMV16X16 * current->quant;                                          int32_t sad8 = IMV16X16 * current->quant;
196    
197                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16) {
   
198                                                  sad8 += pMB->sad8[0] =                                                  sad8 += pMB->sad8[0] =
199                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
200                                                                          pCurrent, 2 * x, 2 * y, pMB->mv16.x,                                                                          pCurrent, 2 * x, 2 * y,
201                                                                          pMB->mv16.y, current->motion_flags,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
202                                                                            current->motion_flags,
203                                                                          current->quant, current->fcode, pParam,                                                                          current->quant, current->fcode, pParam,
204                                                                          pMBs, prevMBs, &pMB->mvs[0],                                                                          pMBs, prevMBs, &pMB->mvs[0],
205                                                                          &pMB->pmvs[0]);                                                                          &pMB->pmvs[0]);
206                                            }
207                                            if (sad8 < pMB->sad16) {
208    
209                                          if (sad8 < pMB->sad16)                                                  predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
210                                                  sad8 += pMB->sad8[1] =                                                  sad8 += pMB->sad8[1] =
211                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
212                                                                          pCurrent, 2 * x + 1, 2 * y, pMB->mv16.x,                                                                          pCurrent, 2 * x + 1, 2 * y,
213                                                                          pMB->mv16.y, current->motion_flags,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
214                                                                            current->motion_flags,
215                                                                          current->quant, current->fcode, pParam,                                                                          current->quant, current->fcode, pParam,
216                                                                          pMBs, prevMBs, &pMB->mvs[1],                                                                          pMBs, prevMBs, &pMB->mvs[1],
217                                                                          &pMB->pmvs[1]);                                                                          &pMB->pmvs[1]);
218                                            }
219                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16) {
220                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
221                                                  sad8 += pMB->sad8[2] =                                                  sad8 += pMB->sad8[2] =
222                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
223                                                                          pCurrent, 2 * x, 2 * y + 1, pMB->mv16.x,                                                                          pCurrent, 2 * x, 2 * y + 1,
224                                                                          pMB->mv16.y, current->motion_flags,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
225                                                                            current->motion_flags,
226                                                                          current->quant, current->fcode, pParam,                                                                          current->quant, current->fcode, pParam,
227                                                                          pMBs, prevMBs, &pMB->mvs[2],                                                                          pMBs, prevMBs, &pMB->mvs[2],
228                                                                          &pMB->pmvs[2]);                                                                          &pMB->pmvs[2]);
229                                            }
230                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16) {
231                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
232                                                  sad8 += pMB->sad8[3] =                                                  sad8 += pMB->sad8[3] =
233                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
234                                                                          pCurrent, 2 * x + 1, 2 * y + 1,                                                                          pCurrent, 2 * x + 1, 2 * y + 1,
235                                                                          pMB->mv16.x, pMB->mv16.y,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
236                                                                          current->motion_flags, current->quant,                                                                          current->motion_flags,
237                                                                          current->fcode, pParam, pMBs, prevMBs,                                                                          current->quant, current->fcode, pParam,
238                                                                          &pMB->mvs[3], &pMB->pmvs[3]);                                                                          pMBs, prevMBs,
239                                                                            &pMB->mvs[3],
240                                                                            &pMB->pmvs[3]);
241                                            }
242    
243                                          /* decide: MODE_INTER or MODE_INTER4V                                          /* decide: MODE_INTER or MODE_INTER4V
244                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
# Line 409  Line 260 
260                          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;
261                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
262                                  pMB->sad16;                                  pMB->sad16;
   
263                  }                  }
264                            }
265    
266          return 0;          return 0;
267  }  }
268    
269    
270  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
271    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
272      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
273    { \    { \
274      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); \
275      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);\
276      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
277      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
278  }  }
279    
280  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
281      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); \
282      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);\
283      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
284      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
285  }  }
# Line 436  Line 289 
289      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
290    { \    { \
291      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); \
292      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);\
293      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
294      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
295  }  }
# Line 446  Line 299 
299      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
300    { \    { \
301      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); \
302      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);\
303      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
304      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
305  }  }
# Line 456  Line 309 
309      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
310    { \    { \
311      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); \
312      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);\
313      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
314      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
315  }  }
# Line 464  Line 317 
317    
318  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
319    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); \
320    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);\
321    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
322    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
323  }  }
# Line 472  Line 325 
325  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
326    { \    { \
327      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); \
328      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);\
329      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
330      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
331  }  }
# Line 482  Line 335 
335      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
336    { \    { \
337      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); \
338      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);\
339      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
340      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
341  }  }
# Line 492  Line 345 
345      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
346    { \    { \
347      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); \
348      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);\
349      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
350      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
351  }  }
# Line 502  Line 355 
355      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
356    { \    { \
357      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); \
358      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);\
359      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
360      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
361  }  }
# Line 528  Line 381 
381          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
382          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
383          int32_t iSAD;          int32_t iSAD;
384          int32_t pred_x,pred_y;          VECTOR pred;
385    
386          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);  
387            pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
388    
389          iSAD = sad16( cur,          iSAD = sad16( cur,
390                  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 394 
394    
395          currMV->x = 0;          currMV->x = 0;
396          currMV->y = 0;          currMV->y = 0;
397          currPMV->x = -pred_x;          currPMV->x = -pred.x;
398          currPMV->y = -pred_y;          currPMV->y = -pred.y;
399    
400          return iSAD;          return iSAD;
401    
# Line 556  Line 410 
410                                           const uint8_t * const cur,                                           const uint8_t * const cur,
411                                           const int x,                                           const int x,
412                                           const int y,                                           const int y,
413                                           int32_t startx,                                     const int start_x,
414                                           int32_t starty,                                     const int start_y,
415                                           int32_t iMinSAD,                                     int iMinSAD,
416                                           VECTOR * const currMV,                                           VECTOR * const currMV,
417                                           const VECTOR * const pmv,                                     const int center_x,
418                                       const int center_y,
419                                           const int32_t min_dx,                                           const int32_t min_dx,
420                                           const int32_t max_dx,                                           const int32_t max_dx,
421                                           const int32_t min_dy,                                           const int32_t min_dy,
# Line 574  Line 429 
429  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
430    
431          int32_t iDirection = 0;          int32_t iDirection = 0;
432            int32_t iDirectionBackup;
433          int32_t iSAD;          int32_t iSAD;
434          VECTOR backupMV;          VECTOR backupMV;
435    
436          backupMV.x = startx;          backupMV.x = start_x;
437          backupMV.y = starty;          backupMV.y = start_y;
438    
439  /* 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 */
440    
# Line 587  Line 443 
443          CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
444          CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
445    
446          if (iDirection)          if (iDirection) {
447                  while (!iFound) {                  while (!iFound) {
448                          iFound = 1;                          iFound = 1;
449                          backupMV = *currMV;                          backupMV = *currMV;
450                            iDirectionBackup = iDirection;
451    
452                          if (iDirection != 2)                          if (iDirectionBackup != 2)
453                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
454                                                                                     backupMV.y, 1);                                                                                     backupMV.y, 1);
455                          if (iDirection != 1)                          if (iDirectionBackup != 1)
456                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
457                                                                                     backupMV.y, 2);                                                                                     backupMV.y, 2);
458                          if (iDirection != 4)                          if (iDirectionBackup != 4)
459                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
460                                                                                     backupMV.y - iDiamondSize, 3);                                                                                     backupMV.y - iDiamondSize, 3);
461                          if (iDirection != 3)                          if (iDirectionBackup != 3)
462                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
463                                                                                     backupMV.y + iDiamondSize, 4);                                                                                     backupMV.y + iDiamondSize, 4);
464                    }
465          } else {          } else {
466                  currMV->x = startx;                  currMV->x = start_x;
467                  currMV->y = starty;                  currMV->y = start_y;
468          }          }
469          return iMinSAD;          return iMinSAD;
470  }  }
# Line 619  Line 477 
477                                          const uint8_t * const cur,                                          const uint8_t * const cur,
478                                          const int x,                                          const int x,
479                                          const int y,                                          const int y,
480                                          int32_t startx,                                     const int start_x,
481                                          int32_t starty,                                     const int start_y,
482                                          int32_t iMinSAD,                                     int iMinSAD,
483                                          VECTOR * const currMV,                                          VECTOR * const currMV,
484                                          const VECTOR * const pmv,                                     const int center_x,
485                                       const int center_y,
486                                          const int32_t min_dx,                                          const int32_t min_dx,
487                                          const int32_t max_dx,                                          const int32_t max_dx,
488                                          const int32_t min_dy,                                          const int32_t min_dy,
# Line 640  Line 499 
499          int32_t iSAD;          int32_t iSAD;
500          VECTOR backupMV;          VECTOR backupMV;
501    
502          backupMV.x = startx;          backupMV.x = start_x;
503          backupMV.y = starty;          backupMV.y = start_y;
504    
505  /* 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 */
506    
# Line 666  Line 525 
525                                                           backupMV.y + iDiamondSize, 8);                                                           backupMV.y + iDiamondSize, 8);
526    
527    
528          if (iDirection)          if (iDirection) {
529                  while (!iFound) {                  while (!iFound) {
530                          iFound = 1;                          iFound = 1;
531                          backupMV = *currMV;                          backupMV = *currMV;
# Line 675  Line 534 
534                          case 1:                          case 1:
535                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
536                                                                                     backupMV.y, 1);                                                                                     backupMV.y, 1);
537                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
538                                                                                   backupMV.y - iDiamondSize, 5);                                                                                   backupMV.y - iDiamondSize, 5);
539                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
540                                                                                   backupMV.y - iDiamondSize, 7);                                                                                   backupMV.y - iDiamondSize, 7);
541                                  break;                                  break;
542                          case 2:                          case 2:
543                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
544                                                                                   2);                                                                                   2);
545                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
546                                                                                   backupMV.y + iDiamondSize, 6);                                                                                   backupMV.y + iDiamondSize, 6);
547                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
548                                                                                   backupMV.y + iDiamondSize, 8);                                                                                   backupMV.y + iDiamondSize, 8);
549                                  break;                                  break;
550    
551                          case 3:                          case 3:
552                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
553                                                                                   4);                                                                                   4);
554                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
555                                                                                   backupMV.y - iDiamondSize, 7);                                                                                   backupMV.y - iDiamondSize, 7);
556                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
557                                                                                   backupMV.y + iDiamondSize, 8);                                                                                   backupMV.y + iDiamondSize, 8);
558                                  break;                                  break;
559    
560                          case 4:                          case 4:
561                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
562                                                                                   3);                                                                                   3);
563                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
564                                                                                   backupMV.y - iDiamondSize, 5);                                                                                   backupMV.y - iDiamondSize, 5);
565                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
566                                                                                   backupMV.y + iDiamondSize, 6);                                                                                   backupMV.y + iDiamondSize, 6);
567                                  break;                                  break;
568    
569                          case 5:                          case 5:
570                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
571                                                                                   1);                                                                                   1);
572                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
573                                                                                   3);                                                                                   3);
574                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
575                                                                                   backupMV.y - iDiamondSize, 5);                                                                                   backupMV.y - iDiamondSize, 5);
576                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
577                                                                                   backupMV.y + iDiamondSize, 6);                                                                                   backupMV.y + iDiamondSize, 6);
578                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
579                                                                                   backupMV.y - iDiamondSize, 7);                                                                                   backupMV.y - iDiamondSize, 7);
580                                  break;                                  break;
581    
582                          case 6:                          case 6:
583                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
584                                                                                   2);                                                                                   2);
585                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
586                                                                                   3);                                                                                   3);
587    
588                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
589                                                                                   backupMV.y - iDiamondSize, 5);                                                                                   backupMV.y - iDiamondSize, 5);
590                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
591                                                                                   backupMV.y + iDiamondSize, 6);                                                                                   backupMV.y + iDiamondSize, 6);
592                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
593                                                                                   backupMV.y + iDiamondSize, 8);                                                                                   backupMV.y + iDiamondSize, 8);
594    
595                                  break;                                  break;
# Line 738  Line 597 
597                          case 7:                          case 7:
598                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
599                                                                                     backupMV.y, 1);                                                                                     backupMV.y, 1);
600                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
601                                                                                   4);                                                                                   4);
602                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
603                                                                                   backupMV.y - iDiamondSize, 5);                                                                                   backupMV.y - iDiamondSize, 5);
604                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
605                                                                                   backupMV.y - iDiamondSize, 7);                                                                                   backupMV.y - iDiamondSize, 7);
606                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
607                                                                                   backupMV.y + iDiamondSize, 8);                                                                                   backupMV.y + iDiamondSize, 8);
608                                  break;                                  break;
609    
610                          case 8:                          case 8:
611                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
612                                                                                   2);                                                                                   2);
613                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
614                                                                                   4);                                                                                   4);
615                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
616                                                                                   backupMV.y + iDiamondSize, 6);                                                                                   backupMV.y + iDiamondSize, 6);
617                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
618                                                                                   backupMV.y - iDiamondSize, 7);                                                                                   backupMV.y - iDiamondSize, 7);
619                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
620                                                                                   backupMV.y + iDiamondSize, 8);                                                                                   backupMV.y + iDiamondSize, 8);
621                                  break;                                  break;
622                          default:                          default:
623                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
624                                                                                   1);                                                                                   1);
625                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
626                                                                                   2);                                                                                   2);
627                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
628                                                                                   3);                                                                                   3);
629                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
630                                                                                   4);                                                                                   4);
631    
632                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
633                                                                                   backupMV.y - iDiamondSize, 5);                                                                                   backupMV.y - iDiamondSize, 5);
634                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
635                                                                                   backupMV.y + iDiamondSize, 6);                                                                                   backupMV.y + iDiamondSize, 6);
636                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
637                                                                                   backupMV.y - iDiamondSize, 7);                                                                                   backupMV.y - iDiamondSize, 7);
638                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
639                                                                                   backupMV.y + iDiamondSize, 8);                                                                                   backupMV.y + iDiamondSize, 8);
640                                  break;                                  break;
641                          }                          }
642                    }
643          } else {          } else {
644                  currMV->x = startx;                  currMV->x = start_x;
645                  currMV->y = starty;                  currMV->y = start_y;
646          }          }
647          return iMinSAD;          return iMinSAD;
648  }  }
# Line 796  Line 656 
656                                    const uint8_t * const cur,                                    const uint8_t * const cur,
657                                    const int x,                                    const int x,
658                                    const int y,                                    const int y,
659                                    int32_t startx,                                     const int start_x,
660                                    int32_t starty,                                     const int start_y,
661                                    int32_t iMinSAD,                                     int iMinSAD,
662                                    VECTOR * const currMV,                                    VECTOR * const currMV,
663                                    const VECTOR * const pmv,                                     const int center_x,
664                                       const int center_y,
665                                    const int32_t min_dx,                                    const int32_t min_dx,
666                                    const int32_t max_dx,                                    const int32_t max_dx,
667                                    const int32_t min_dy,                                    const int32_t min_dy,
# Line 815  Line 676 
676          int32_t dx, dy;          int32_t dx, dy;
677          VECTOR backupMV;          VECTOR backupMV;
678    
679          backupMV.x = startx;          backupMV.x = start_x;
680          backupMV.y = starty;          backupMV.y = start_y;
681    
682          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
683                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
# Line 833  Line 694 
694                                                  const uint8_t * const cur,                                                  const uint8_t * const cur,
695                                                  const int x,                                                  const int x,
696                                                  const int y,                                                  const int y,
697                                                  int32_t startx,                                             int start_x,
698                                                  int32_t starty,                                             int start_y,
699                                                  int32_t iMinSAD,                                             int iMinSAD,
700                                                  VECTOR * const currMV,                                                  VECTOR * const currMV,
701                                                  const VECTOR * const pmv,                                             const int center_x,
702                                               const int center_y,
703                                                  const int32_t min_dx,                                                  const int32_t min_dx,
704                                                  const int32_t max_dx,                                                  const int32_t max_dx,
705                                                  const int32_t min_dy,                                                  const int32_t min_dy,
# Line 854  Line 716 
716  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
717    
718          if (iDirection) {          if (iDirection) {
719                  CHECK_MV16_CANDIDATE(startx - iDiamondSize, starty);                  CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
720                  CHECK_MV16_CANDIDATE(startx + iDiamondSize, starty);                  CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
721                  CHECK_MV16_CANDIDATE(startx, starty - iDiamondSize);                  CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
722                  CHECK_MV16_CANDIDATE(startx, starty + iDiamondSize);                  CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
723          } else {          } else {
724                  int bDirection = 1 + 2 + 4 + 8;                  int bDirection = 1 + 2 + 4 + 8;
725    
726                  do {                  do {
727                          iDirection = 0;                          iDirection = 0;
728                          if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)                          if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
729                                  CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);                                  CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
730    
731                          if (bDirection & 2)                          if (bDirection & 2)
732                                  CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);                                  CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
733    
734                          if (bDirection & 4)                          if (bDirection & 4)
735                                  CHECK_MV16_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
736    
737                          if (bDirection & 8)                          if (bDirection & 8)
738                                  CHECK_MV16_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
739    
740                          /* now we're doing diagonal checks near our candidate */                          /* now we're doing diagonal checks near our candidate */
741    
# Line 881  Line 743 
743                          {                          {
744                                  bDirection = iDirection;                                  bDirection = iDirection;
745                                  iDirection = 0;                                  iDirection = 0;
746                                  startx = currMV->x;                                  start_x = currMV->x;
747                                  starty = currMV->y;                                  start_y = currMV->y;
748                                  if (bDirection & 3)     //our candidate is left or right                                  if (bDirection & 3)     //our candidate is left or right
749                                  {                                  {
750                                          CHECK_MV16_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);                                          CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
751                                          CHECK_MV16_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);                                          CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
752                                  } else                  // what remains here is up or down                                  } else                  // what remains here is up or down
753                                  {                                  {
754                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
755                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
756                                  }                                  }
757    
758                                  if (iDirection) {                                  if (iDirection) {
759                                          bDirection += iDirection;                                          bDirection += iDirection;
760                                          startx = currMV->x;                                          start_x = currMV->x;
761                                          starty = currMV->y;                                          start_y = currMV->y;
762                                  }                                  }
763                          } else                          //about to quit, eh? not so fast....                          } else                          //about to quit, eh? not so fast....
764                          {                          {
765                                  switch (bDirection) {                                  switch (bDirection) {
766                                  case 2:                                  case 2:
767                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
768                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
769                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
770                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
771                                          break;                                          break;
772                                  case 1:                                  case 1:
773                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,  
774                                                                                           starty - iDiamondSize, 1 + 4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
775                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                                                                           start_y - iDiamondSize, 1 + 4);
776                                                                                           starty + iDiamondSize, 1 + 8);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
777                                                                                             start_y + iDiamondSize, 1 + 8);
778                                          break;                                          break;
779                                  case 2 + 4:                                  case 2 + 4:
780                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
781                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
782                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
783                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
784                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
785                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
786                                          break;                                          break;
787                                  case 4:                                  case 4:
788                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
789                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
790                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
791                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
792                                          break;                                          break;
793                                  case 8:                                  case 8:
794                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
795                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
796                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
797                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
798                                          break;                                          break;
799                                  case 1 + 4:                                  case 1 + 4:
800                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
801                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
802                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
803                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
804                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
805                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
806                                          break;                                          break;
807                                  case 2 + 8:                                  case 2 + 8:
808                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
809                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
810                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
811                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
812                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
813                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
814                                          break;                                          break;
815                                  case 1 + 8:                                  case 1 + 8:
816                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
817                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
818                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
819                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
820                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
821                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
822                                          break;                                          break;
823                                  default:                //1+2+4+8 == we didn't find anything at all                                  default:                //1+2+4+8 == we didn't find anything at all
824                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
825                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
826                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
827                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
828                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
829                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
830                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
831                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
832                                          break;                                          break;
833                                  }                                  }
834                                  if (!iDirection)                                  if (!iDirection)
835                                          break;          //ok, the end. really                                          break;          //ok, the end. really
836                                  else {                                  else {
837                                          bDirection = iDirection;                                          bDirection = iDirection;
838                                          startx = currMV->x;                                          start_x = currMV->x;
839                                          starty = currMV->y;                                          start_y = currMV->y;
840                                  }                                  }
841                          }                          }
842                  }                  }
# Line 982  Line 845 
845          return iMinSAD;          return iMinSAD;
846  }  }
847    
848    #define CHECK_MV16_F_INTERPOL(X,Y) { \
849      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
850        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
851      { \
852        iSAD = sad16bi( cur, \
853                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
854                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
855                            iEdgedWidth); \
856        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
857        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
858        if (iSAD < iMinSAD) \
859        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); } } \
860    }
861    
862    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y) { \
863      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
864        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
865      { \
866        iSAD = sad16bi( cur, \
867                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
868                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
869                            iEdgedWidth); \
870        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
871        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
872        if (iSAD < iMinSAD) \
873        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); iFound=0;} } \
874    }
875    
876    #define CHECK_MV16_B_INTERPOL(X,Y) { \
877      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
878        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
879      { \
880        iSAD = sad16bi( cur, \
881                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
882                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
883                            iEdgedWidth); \
884        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
885        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
886        if (iSAD < iMinSAD) \
887        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); } } \
888    }
889    
890    #define CHECK_MV16_B_INTERPOL_FOUND(X,Y) { \
891      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
892        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
893      { \
894        iSAD = sad16bi( cur, \
895                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
896                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
897                            iEdgedWidth); \
898        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
899        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
900        if (iSAD < iMinSAD) \
901        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); iFound=0;} } \
902    }
903    
904  int32_t  int32_t
905  AdvDiamond8_MainSearch(const uint8_t * const pRef,  Diamond16_InterpolMainSearch(
906                                             const uint8_t * const pRefH,                                          const uint8_t * const f_pRef,
907                                             const uint8_t * const pRefV,                                           const uint8_t * const f_pRefH,
908                                             const uint8_t * const pRefHV,                                           const uint8_t * const f_pRefV,
909                                             const uint8_t * const f_pRefHV,
910    
911                                             const uint8_t * const cur,                                             const uint8_t * const cur,
912    
913                                            const uint8_t * const b_pRef,
914                                             const uint8_t * const b_pRefH,
915                                             const uint8_t * const b_pRefV,
916                                             const uint8_t * const b_pRefHV,
917    
918                                             const int x,                                             const int x,
919                                             const int y,                                             const int y,
920                                             int32_t startx,  
921                                             int32_t starty,                                     const int f_start_x,
922                                             int32_t iMinSAD,                                     const int f_start_y,
923                                             VECTOR * const currMV,                                     const int b_start_x,
924                                             const VECTOR * const pmv,                                     const int b_start_y,
925                                             const int32_t min_dx,  
926                                             const int32_t max_dx,                                     int iMinSAD,
927                                             const int32_t min_dy,                                     VECTOR * const f_currMV,
928                                             const int32_t max_dy,                                     VECTOR * const b_currMV,
929    
930                                       const int f_center_x,
931                                       const int f_center_y,
932                                       const int b_center_x,
933                                       const int b_center_y,
934    
935                                        const int32_t f_min_dx,
936                                            const int32_t f_max_dx,
937                                            const int32_t f_min_dy,
938                                            const int32_t f_max_dy,
939    
940                                        const int32_t b_min_dx,
941                                            const int32_t b_max_dx,
942                                            const int32_t b_min_dy,
943                                            const int32_t b_max_dy,
944    
945                                             const int32_t iEdgedWidth,                                             const int32_t iEdgedWidth,
946                                             const int32_t iDiamondSize,                                             const int32_t iDiamondSize,
947                                             const int32_t iFcode,  
948                                            const int32_t f_iFcode,
949                                            const int32_t b_iFcode,
950    
951                                             const int32_t iQuant,                                             const int32_t iQuant,
952                                             int iDirection)                                          int iFound)
953  {  {
954    /* Do a diamond search around given starting point, return SAD of best */
955    
956          int32_t iSAD;          int32_t iSAD;
957    
958  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */          VECTOR f_backupMV;
959            VECTOR b_backupMV;
960    
961          if (iDirection) {          f_currMV->x = f_start_x;
962                  CHECK_MV8_CANDIDATE(startx - iDiamondSize, starty);          f_currMV->y = f_start_y;
963                  CHECK_MV8_CANDIDATE(startx + iDiamondSize, starty);          b_currMV->x = b_start_x;
964                  CHECK_MV8_CANDIDATE(startx, starty - iDiamondSize);          b_currMV->y = b_start_y;
                 CHECK_MV8_CANDIDATE(startx, starty + iDiamondSize);  
         } else {  
                 int bDirection = 1 + 2 + 4 + 8;  
965    
966                  do {          do
967                          iDirection = 0;          {
968                          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)                  iFound = 1;
                                 CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);  
969    
970                          if (bDirection & 2)                  f_backupMV = *f_currMV;
                                 CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);  
971    
972                          if (bDirection & 4)                  CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x - iDiamondSize, f_backupMV.y);
973                                  CHECK_MV8_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);                  CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x + iDiamondSize, f_backupMV.y);
974                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y - iDiamondSize);
975                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y + iDiamondSize);
976    
977                          if (bDirection & 8)                  b_backupMV = *b_currMV;
                                 CHECK_MV8_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);  
978    
979                          /* now we're doing diagonal checks near our candidate */                  CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x - iDiamondSize, b_backupMV.y);
980                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x + iDiamondSize, b_backupMV.y);
981                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y - iDiamondSize);
982                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y + iDiamondSize);
983    
984                          if (iDirection)         //checking if anything found          } while (!iFound);
985                          {  
986            return iMinSAD;
987    }
988    
989    /* Sorry, these MACROS really got too large... I'll turn them into function soon! */
990    
991    #define CHECK_MV16_DIRECT_FOUND(X,Y) \
992            if ( (X)>=(-32) && (X)<=(31) && ((Y)>=-32) && ((Y)<=31) ) \
993            { int k;\
994            VECTOR mvs,b_mvs;       \
995            iSAD = 0;\
996            for (k = 0; k < 4; k++) {       \
997                                            mvs.x = (int32_t) ((TRB * directmv[k].x) / TRD + (X));          \
998                        b_mvs.x = (int32_t) (((X) == 0)                                                     \
999                                                                                    ? ((TRB - TRD) * directmv[k].x) / TRD   \
1000                                                : mvs.x - directmv[k].x);                           \
1001                                                                                                                                                                    \
1002                        mvs.y = (int32_t) ((TRB * directmv[k].y) / TRD + (Y));              \
1003                            b_mvs.y = (int32_t) (((Y) == 0)                                                         \
1004                                                                                    ? ((TRB - TRD) * directmv[k].y) / TRD   \
1005                                                : mvs.y - directmv[k].y);                           \
1006                                                                                                                                                                    \
1007      if ( (mvs.x <= max_dx) && (mvs.x >= min_dx) \
1008        && (mvs.y <= max_dy) && (mvs.y >= min_dy)  \
1009            && (b_mvs.x <= max_dx) && (b_mvs.x >= min_dx)  \
1010        && (b_mvs.y <= max_dy) && (b_mvs.y >= min_dy) ) { \
1011                iSAD += sad8bi( cur + 8*(k&1) + 8*(k>>1)*iEdgedWidth,                                                                                                       \
1012                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1013                                            mvs.x, mvs.y, iEdgedWidth),                                                             \
1014                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1015                                            b_mvs.x, b_mvs.y, iEdgedWidth),                                                         \
1016                            iEdgedWidth); \
1017                    }       \
1018            else    \
1019                    iSAD = 65535;   \
1020            } \
1021            iSAD += calc_delta_16((X),(Y), 1, iQuant);\
1022            if (iSAD < iMinSAD) \
1023                {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iFound=0; } \
1024    }
1025    
1026    
1027    
1028    int32_t
1029    Diamond16_DirectMainSearch(
1030                                            const uint8_t * const f_pRef,
1031                                            const uint8_t * const f_pRefH,
1032                                            const uint8_t * const f_pRefV,
1033                                            const uint8_t * const f_pRefHV,
1034    
1035                                            const uint8_t * const cur,
1036    
1037                                            const uint8_t * const b_pRef,
1038                                            const uint8_t * const b_pRefH,
1039                                            const uint8_t * const b_pRefV,
1040                                            const uint8_t * const b_pRefHV,
1041    
1042                                            const int x,
1043                                            const int y,
1044    
1045                                            const int TRB,
1046                                            const int TRD,
1047    
1048                                        const int start_x,
1049                                        const int start_y,
1050    
1051                                        int iMinSAD,
1052                                        VECTOR * const currMV,
1053                                            const VECTOR * const directmv,
1054    
1055                                        const int32_t min_dx,
1056                                            const int32_t max_dx,
1057                                            const int32_t min_dy,
1058                                            const int32_t max_dy,
1059    
1060                                            const int32_t iEdgedWidth,
1061                                            const int32_t iDiamondSize,
1062    
1063                                            const int32_t iQuant,
1064                                            int iFound)
1065    {
1066    /* Do a diamond search around given starting point, return SAD of best */
1067    
1068            int32_t iSAD;
1069    
1070            VECTOR backupMV;
1071    
1072            currMV->x = start_x;
1073            currMV->y = start_y;
1074    
1075    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1076    
1077            do
1078            {
1079                    iFound = 1;
1080    
1081                    backupMV = *currMV;
1082    
1083                    CHECK_MV16_DIRECT_FOUND(backupMV.x - iDiamondSize, backupMV.y);
1084                    CHECK_MV16_DIRECT_FOUND(backupMV.x + iDiamondSize, backupMV.y);
1085                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y - iDiamondSize);
1086                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y + iDiamondSize);
1087    
1088            } while (!iFound);
1089    
1090            return iMinSAD;
1091    }
1092    
1093    
1094    int32_t
1095    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1096                                               const uint8_t * const pRefH,
1097                                               const uint8_t * const pRefV,
1098                                               const uint8_t * const pRefHV,
1099                                               const uint8_t * const cur,
1100                                               const int x,
1101                                               const int y,
1102                                               int start_x,
1103                                               int start_y,
1104                                               int iMinSAD,
1105                                               VECTOR * const currMV,
1106                                               const int center_x,
1107                                               const int center_y,
1108                                               const int32_t min_dx,
1109                                               const int32_t max_dx,
1110                                               const int32_t min_dy,
1111                                               const int32_t max_dy,
1112                                               const int32_t iEdgedWidth,
1113                                               const int32_t iDiamondSize,
1114                                               const int32_t iFcode,
1115                                               const int32_t iQuant,
1116                                               int iDirection)
1117    {
1118    
1119            int32_t iSAD;
1120    
1121    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1122    
1123            if (iDirection) {
1124                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1125                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1126                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1127                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1128            } else {
1129                    int bDirection = 1 + 2 + 4 + 8;
1130    
1131                    do {
1132                            iDirection = 0;
1133                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
1134                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1135    
1136                            if (bDirection & 2)
1137                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1138    
1139                            if (bDirection & 4)
1140                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1141    
1142                            if (bDirection & 8)
1143                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1144    
1145                            /* now we're doing diagonal checks near our candidate */
1146    
1147                            if (iDirection)         //checking if anything found
1148                            {
1149                                  bDirection = iDirection;                                  bDirection = iDirection;
1150                                  iDirection = 0;                                  iDirection = 0;
1151                                  startx = currMV->x;                                  start_x = currMV->x;
1152                                  starty = currMV->y;                                  start_y = currMV->y;
1153                                  if (bDirection & 3)     //our candidate is left or right                                  if (bDirection & 3)     //our candidate is left or right
1154                                  {                                  {
1155                                          CHECK_MV8_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1156                                          CHECK_MV8_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1157                                  } else                  // what remains here is up or down                                  } else                  // what remains here is up or down
1158                                  {                                  {
1159                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1160                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1161                                  }                                  }
1162    
1163                                  if (iDirection) {                                  if (iDirection) {
1164                                          bDirection += iDirection;                                          bDirection += iDirection;
1165                                          startx = currMV->x;                                          start_x = currMV->x;
1166                                          starty = currMV->y;                                          start_y = currMV->y;
1167                                  }                                  }
1168                          } else                          //about to quit, eh? not so fast....                          } else                          //about to quit, eh? not so fast....
1169                          {                          {
1170                                  switch (bDirection) {                                  switch (bDirection) {
1171                                  case 2:                                  case 2:
1172                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1173                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1174                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1175                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1176                                          break;                                          break;
1177                                  case 1:                                  case 1:
1178                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1179                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1180                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1181                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1182                                          break;                                          break;
1183                                  case 2 + 4:                                  case 2 + 4:
1184                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1185                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1186                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1187                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1188                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1189                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1190                                          break;                                          break;
1191                                  case 4:                                  case 4:
1192                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1193                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1194                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1195                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1196                                          break;                                          break;
1197                                  case 8:                                  case 8:
1198                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1199                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1200                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1201                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1202                                          break;                                          break;
1203                                  case 1 + 4:                                  case 1 + 4:
1204                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1205                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1206                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1207                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1208                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1209                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1210                                          break;                                          break;
1211                                  case 2 + 8:                                  case 2 + 8:
1212                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1213                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1214                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1215                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1216                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1217                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1218                                          break;                                          break;
1219                                  case 1 + 8:                                  case 1 + 8:
1220                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1221                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1222                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1223                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1224                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1225                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1226                                          break;                                          break;
1227                                  default:                //1+2+4+8 == we didn't find anything at all                                  default:                //1+2+4+8 == we didn't find anything at all
1228                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1229                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1230                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1231                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1232                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1233                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1234                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1235                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1236                                          break;                                          break;
1237                                  }                                  }
1238                                  if (!(iDirection))                                  if (!(iDirection))
1239                                          break;          //ok, the end. really                                          break;          //ok, the end. really
1240                                  else {                                  else {
1241                                          bDirection = iDirection;                                          bDirection = iDirection;
1242                                          startx = currMV->x;                                          start_x = currMV->x;
1243                                          starty = currMV->y;                                          start_y = currMV->y;
1244                                  }                                  }
1245                          }                          }
1246                  }                  }
# Line 1148  Line 1258 
1258                                   const uint8_t * const cur,                                   const uint8_t * const cur,
1259                                   const int x,                                   const int x,
1260                                   const int y,                                   const int y,
1261                                   int32_t startx,                             const int start_x,
1262                                   int32_t starty,                             const int start_y,
1263                                   int32_t iMinSAD,                             int iMinSAD,
1264                                   VECTOR * const currMV,                                   VECTOR * const currMV,
1265                                   const VECTOR * const pmv,                             const int center_x,
1266                               const int center_y,
1267                                   const int32_t min_dx,                                   const int32_t min_dx,
1268                                   const int32_t max_dx,                                   const int32_t max_dx,
1269                                   const int32_t min_dy,                                   const int32_t min_dy,
# Line 1167  Line 1278 
1278          int32_t dx, dy;          int32_t dx, dy;
1279          VECTOR backupMV;          VECTOR backupMV;
1280    
1281          backupMV.x = startx;          backupMV.x = start_x;
1282          backupMV.y = starty;          backupMV.y = start_y;
1283    
1284          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1285                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
# Line 1177  Line 1288 
1288          return iMinSAD;          return iMinSAD;
1289  }  }
1290    
1291    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1292    
1293  int32_t  int32_t
1294  Halfpel16_Refine(const uint8_t * const pRef,  Halfpel16_Refine(const uint8_t * const pRef,
# Line 1189  Line 1300 
1300                                   const int y,                                   const int y,
1301                                   VECTOR * const currMV,                                   VECTOR * const currMV,
1302                                   int32_t iMinSAD,                                   int32_t iMinSAD,
1303                                   const VECTOR * const pmv,                             const int center_x,
1304                               const int center_y,
1305                                   const int32_t min_dx,                                   const int32_t min_dx,
1306                                   const int32_t max_dx,                                   const int32_t max_dx,
1307                                   const int32_t min_dy,                                   const int32_t min_dy,
# Line 1218  Line 1330 
1330  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1331    
1332    
1333    
1334  int32_t  int32_t
1335  PMVfastSearch16(const uint8_t * const pRef,  PMVfastSearch16(const uint8_t * const pRef,
1336                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
# Line 1226  Line 1339 
1339                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1340                                  const int x,                                  const int x,
1341                                  const int y,                                  const int y,
1342                                    const int start_x,      /* start is searched first, so it should contain the most */
1343                                    const int start_y,  /* likely motion vector for this block */
1344                                    const int center_x,     /* center is from where length of MVs is measured */
1345                                    const int center_y,
1346                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1347                                  const uint32_t iQuant,                                  const uint32_t iQuant,
1348                                  const uint32_t iFcode,                                  const uint32_t iFcode,
# Line 1259  Line 1376 
1376    
1377          MainSearch16FuncPtr MainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
1378    
 //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
1379          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1380    
1381          static int32_t threshA, threshB;          int32_t threshA, threshB;
1382          int32_t bPredEq;          int32_t bPredEq;
1383          int32_t iMinSAD, iSAD;          int32_t iMinSAD, iSAD;
1384    
# Line 1280  Line 1396 
1396          }          }
1397    
1398          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1399          bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1400            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1401    
1402          if ((x == 0) && (y == 0)) {          if ((x == 0) && (y == 0)) {
1403                  threshA = 512;                  threshA = 512;
1404                  threshB = 1024;                  threshB = 1024;
   
1405          } else {          } else {
1406                  threshA = psad[0];                  threshA = psad[0];
1407                  threshB = threshA + 256;                  threshB = threshA + 256;
# Line 1306  Line 1422 
1422     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1423  */  */
1424    
1425          *currMV = pmv[0];                       /* current best := prediction */          currMV->x = start_x;
1426            currMV->y = start_y;
1427    
1428          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
1429                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1430                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
# Line 1330  Line 1448 
1448                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1449                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1450          iMinSAD +=          iMinSAD +=
1451                  calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1452                                            (uint8_t) iFcode, iQuant);                                            (uint8_t) iFcode, iQuant);
1453    
1454          if ((iMinSAD < 256) ||          if ((iMinSAD < 256) ||
1455                  ((MVequal(*currMV, prevMB->mvs[0])) &&                  ((MVequal(*currMV, prevMB->mvs[0])) &&
1456                   ((uint32_t) iMinSAD < prevMB->sad16))) {                   ((int32_t) iMinSAD < prevMB->sad16))) {
1457                  if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode                  if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1458                  {                  {
1459                          if (!MVzero(*currMV)) {                          if (!MVzero(*currMV)) {
# Line 1439  Line 1557 
1557    
1558          if ((iMinSAD <= threshA) ||          if ((iMinSAD <= threshA) ||
1559                  (MVequal(*currMV, prevMB->mvs[0]) &&                  (MVequal(*currMV, prevMB->mvs[0]) &&
1560                   ((uint32_t) iMinSAD < prevMB->sad16))) {                   ((int32_t) iMinSAD < prevMB->sad16))) {
1561                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1562                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1563                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1466  Line 1584 
1584    
1585          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
1586    
1587    
1588  /* 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 */
1589          iSAD =          iSAD =
1590                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1591                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1592                                                      min_dx, max_dx,
1593                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1594                                                    iQuant, iFound);                                                    iQuant, iFound);
1595    
# Line 1484  Line 1604 
1604                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
1605                          iSAD =                          iSAD =
1606                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1607                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1608                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1609                                                                    iDiamondSize, iFcode, iQuant, iFound);                                                                    iDiamondSize, iFcode, iQuant, iFound);
1610    
# Line 1497  Line 1617 
1617                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1618                          iSAD =                          iSAD =
1619                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1620                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y,
1621                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                                    min_dx, max_dx, min_dy, max_dy,
1622                                                                      iEdgedWidth, iDiamondSize, iFcode,
1623                                                                    iQuant, iFound);                                                                    iQuant, iFound);
1624    
1625                          if (iSAD < iMinSAD) {                          if (iSAD < iMinSAD) {
# Line 1516  Line 1637 
1637          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
1638                  iMinSAD =                  iMinSAD =
1639                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1640                                                           iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1641                                                           iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1642    
1643    PMVfast16_Terminate_without_Refine:    PMVfast16_Terminate_without_Refine:
1644          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1645          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1646          return iMinSAD;          return iMinSAD;
1647  }  }
1648    
# Line 1538  Line 1659 
1659                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1660                                          const int x,                                          const int x,
1661                                          const int y,                                          const int y,
1662                                          int32_t startx,                                          int32_t start_x,
1663                                          int32_t starty,                                          int32_t start_y,
1664                                          int32_t iMinSAD,                                          int32_t iMinSAD,
1665                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1666                                          const VECTOR * const pmv,                                     const int center_x,
1667                                       const int center_y,
1668                                          const int32_t min_dx,                                          const int32_t min_dx,
1669                                          const int32_t max_dx,                                          const int32_t max_dx,
1670                                          const int32_t min_dy,                                          const int32_t min_dy,
# Line 1556  Line 1678 
1678  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1679    
1680          int32_t iDirection = 0;          int32_t iDirection = 0;
1681            int32_t iDirectionBackup;
1682          int32_t iSAD;          int32_t iSAD;
1683          VECTOR backupMV;          VECTOR backupMV;
1684    
1685          backupMV.x = startx;          backupMV.x = start_x;
1686          backupMV.y = starty;          backupMV.y = start_y;
1687    
1688  /* 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 */
1689    
# Line 1569  Line 1692 
1692          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1693          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1694    
1695          if (iDirection)          if (iDirection) {
1696                  while (!iFound) {                  while (!iFound) {
1697                          iFound = 1;                          iFound = 1;
1698                          backupMV = *currMV;     // since iDirection!=0, this is well defined!                          backupMV = *currMV;     // since iDirection!=0, this is well defined!
1699                            iDirectionBackup = iDirection;
1700    
1701                          if (iDirection != 2)                          if (iDirectionBackup != 2)
1702                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1703                                                                                    backupMV.y, 1);                                                                                    backupMV.y, 1);
1704                          if (iDirection != 1)                          if (iDirectionBackup != 1)
1705                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1706                                                                                    backupMV.y, 2);                                                                                    backupMV.y, 2);
1707                          if (iDirection != 4)                          if (iDirectionBackup != 4)
1708                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1709                                                                                    backupMV.y - iDiamondSize, 3);                                                                                    backupMV.y - iDiamondSize, 3);
1710                          if (iDirection != 3)                          if (iDirectionBackup != 3)
1711                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1712                                                                                    backupMV.y + iDiamondSize, 4);                                                                                    backupMV.y + iDiamondSize, 4);
1713                    }
1714          } else {          } else {
1715                  currMV->x = startx;                  currMV->x = start_x;
1716                  currMV->y = starty;                  currMV->y = start_y;
1717          }          }
1718          return iMinSAD;          return iMinSAD;
1719  }  }
1720    
1721    
1722    
1723    
1724  int32_t  int32_t
1725  Halfpel8_Refine(const uint8_t * const pRef,  Square8_MainSearch(const uint8_t * const pRef,
1726                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
1727                                  const uint8_t * const pRefV,                                  const uint8_t * const pRefV,
1728                                  const uint8_t * const pRefHV,                                  const uint8_t * const pRefHV,
1729                                  const uint8_t * const cur,                                  const uint8_t * const cur,
1730                                  const int x,                                  const int x,
1731                                  const int y,                                  const int y,
1732                                  VECTOR * const currMV,                                          int32_t start_x,
1733                                            int32_t start_y,
1734                                  int32_t iMinSAD,                                  int32_t iMinSAD,
1735                                  const VECTOR * const pmv,                                          VECTOR * const currMV,
1736                                       const int center_x,
1737                                       const int center_y,
1738                                  const int32_t min_dx,                                  const int32_t min_dx,
1739                                  const int32_t max_dx,                                  const int32_t max_dx,
1740                                  const int32_t min_dy,                                  const int32_t min_dy,
1741                                  const int32_t max_dy,                                  const int32_t max_dy,
1742                                            const int32_t iEdgedWidth,
1743                                            const int32_t iDiamondSize,
1744                                  const int32_t iFcode,                                  const int32_t iFcode,
1745                                  const int32_t iQuant,                                  const int32_t iQuant,
1746                                  const int32_t iEdgedWidth)                                          int iFound)
1747  {  {
1748  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a square search around given starting point, return SAD of best */
1749    
1750            int32_t iDirection = 0;
1751          int32_t iSAD;          int32_t iSAD;
1752          VECTOR backupMV = *currMV;          VECTOR backupMV;
   
         CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y - 1);  
         CHECK_MV8_CANDIDATE(backupMV.x, backupMV.y - 1);  
         CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y - 1);  
         CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y);  
         CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y);  
         CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y + 1);  
         CHECK_MV8_CANDIDATE(backupMV.x, backupMV.y + 1);  
         CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y + 1);  
1753    
1754          return iMinSAD;          backupMV.x = start_x;
1755  }          backupMV.y = start_y;
1756    
1757    /* It's one search with full square pattern, and new parts for all following diamonds */
1758    
1759  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  /*   new direction are extra, so 1-4 is normal diamond
1760          537
1761          1*2
1762          648
1763    */
1764    
1765  int32_t          CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1766  PMVfastSearch8(const uint8_t * const pRef,          CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1767                             const uint8_t * const pRefH,          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1768                             const uint8_t * const pRefV,          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
                            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)  
 {  
         const uint32_t iWcount = pParam->mb_width;  
         const int32_t iWidth = pParam->width;  
         const int32_t iHeight = pParam->height;  
         const int32_t iEdgedWidth = pParam->edged_width;  
1769    
1770          const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;          CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1771                                                             backupMV.y - iDiamondSize, 5);
1772            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1773                                                             backupMV.y + iDiamondSize, 6);
1774            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1775                                                             backupMV.y - iDiamondSize, 7);
1776            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1777                                                             backupMV.y + iDiamondSize, 8);
1778    
         int32_t iDiamondSize;  
1779    
1780          int32_t min_dx;          if (iDirection) {
1781          int32_t max_dx;                  while (!iFound) {
1782          int32_t min_dy;                          iFound = 1;
1783          int32_t max_dy;                          backupMV = *currMV;
1784    
1785          VECTOR pmv[4];                          switch (iDirection) {
1786          int32_t psad[4];                          case 1:
1787          VECTOR newMV;                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1788          VECTOR backupMV;                                                                                     backupMV.y, 1);
1789          VECTOR startMV;                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1790                                                                                     backupMV.y - iDiamondSize, 5);
1791                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1792                                                                                     backupMV.y - iDiamondSize, 7);
1793                                    break;
1794                            case 2:
1795                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1796                                                                                     2);
1797                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1798                                                                                     backupMV.y + iDiamondSize, 6);
1799                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1800                                                                                     backupMV.y + iDiamondSize, 8);
1801                                    break;
1802    
1803  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;                          case 3:
1804          const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1805                                                                                     4);
1806                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1807                                                                                     backupMV.y - iDiamondSize, 7);
1808                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1809                                                                                     backupMV.y + iDiamondSize, 8);
1810                                    break;
1811    
1812          static int32_t threshA, threshB;                          case 4:
1813          int32_t iFound, bPredEq;                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1814          int32_t iMinSAD, iSAD;                                                                                   3);
1815                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1816                                                                                     backupMV.y - iDiamondSize, 5);
1817                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1818                                                                                     backupMV.y + iDiamondSize, 6);
1819                                    break;
1820    
1821          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);                          case 5:
1822                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1823                                                                                     1);
1824                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1825                                                                                     3);
1826                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1827                                                                                     backupMV.y - iDiamondSize, 5);
1828                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1829                                                                                     backupMV.y + iDiamondSize, 6);
1830                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1831                                                                                     backupMV.y - iDiamondSize, 7);
1832                                    break;
1833    
1834          MainSearch8FuncPtr MainSearchPtr;                          case 6:
1835                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1836                                                                                     2);
1837                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1838                                                                                     3);
1839    
1840          /* Init variables */                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1841          startMV.x = start_x;                                                                                   backupMV.y - iDiamondSize, 5);
1842          startMV.y = start_y;                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1843                                                                                     backupMV.y + iDiamondSize, 6);
1844                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1845                                                                                     backupMV.y + iDiamondSize, 8);
1846    
1847          /* Get maximum range */                                  break;
         get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,  
                           iFcode);  
1848    
1849          if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {                          case 7:
1850                  min_dx = EVEN(min_dx);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1851                  max_dx = EVEN(max_dx);                                                                                     backupMV.y, 1);
1852                  min_dy = EVEN(min_dy);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1853                                                                                     4);
1854                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1855                                                                                     backupMV.y - iDiamondSize, 5);
1856                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1857                                                                                     backupMV.y - iDiamondSize, 7);
1858                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1859                                                                                     backupMV.y + iDiamondSize, 8);
1860                                    break;
1861    
1862                            case 8:
1863                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1864                                                                                     2);
1865                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1866                                                                                     4);
1867                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1868                                                                                     backupMV.y + iDiamondSize, 6);
1869                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1870                                                                                     backupMV.y - iDiamondSize, 7);
1871                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1872                                                                                     backupMV.y + iDiamondSize, 8);
1873                                    break;
1874                            default:
1875                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1876                                                                                     1);
1877                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1878                                                                                     2);
1879                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1880                                                                                     3);
1881                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1882                                                                                     4);
1883    
1884                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1885                                                                                     backupMV.y - iDiamondSize, 5);
1886                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1887                                                                                     backupMV.y + iDiamondSize, 6);
1888                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1889                                                                                     backupMV.y - iDiamondSize, 7);
1890                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1891                                                                                     backupMV.y + iDiamondSize, 8);
1892                                    break;
1893                            }
1894                    }
1895            } else {
1896                    currMV->x = start_x;
1897                    currMV->y = start_y;
1898            }
1899            return iMinSAD;
1900    }
1901    
1902    
1903    
1904    
1905    
1906    int32_t
1907    Halfpel8_Refine_c(const uint8_t * const pRef,
1908                                    const uint8_t * const pRefH,
1909                                    const uint8_t * const pRefV,
1910                                    const uint8_t * const pRefHV,
1911                                    const uint8_t * const cur,
1912                                    const int x,
1913                                    const int y,
1914                                    VECTOR * const currMV,
1915                                    int32_t iMinSAD,
1916                               const int center_x,
1917                               const int center_y,
1918                                    const int32_t min_dx,
1919                                    const int32_t max_dx,
1920                                    const int32_t min_dy,
1921                                    const int32_t max_dy,
1922                                    const int32_t iFcode,
1923                                    const int32_t iQuant,
1924                                    const int32_t iEdgedWidth)
1925    {
1926    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1927    
1928            int32_t iSAD;
1929            VECTOR backupMV = *currMV;
1930    
1931            CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1932            CHECK_MV8_CANDIDATE(backupMV.x, backupMV.y - 1);
1933            CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1934            CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y);
1935            CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y);
1936            CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1937            CHECK_MV8_CANDIDATE(backupMV.x, backupMV.y + 1);
1938            CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1939    
1940            return iMinSAD;
1941    }
1942    
1943    
1944    #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1945    
1946    int32_t
1947    PMVfastSearch8(const uint8_t * const pRef,
1948                               const uint8_t * const pRefH,
1949                               const uint8_t * const pRefV,
1950                               const uint8_t * const pRefHV,
1951                               const IMAGE * const pCur,
1952                               const int x,
1953                               const int y,
1954                               const int start_x,
1955                               const int start_y,
1956                                    const int center_x,
1957                                    const int center_y,
1958                               const uint32_t MotionFlags,
1959                               const uint32_t iQuant,
1960                               const uint32_t iFcode,
1961                               const MBParam * const pParam,
1962                               const MACROBLOCK * const pMBs,
1963                               const MACROBLOCK * const prevMBs,
1964                               VECTOR * const currMV,
1965                               VECTOR * const currPMV)
1966    {
1967            const uint32_t iWcount = pParam->mb_width;
1968            const int32_t iWidth = pParam->width;
1969            const int32_t iHeight = pParam->height;
1970            const int32_t iEdgedWidth = pParam->edged_width;
1971    
1972            const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;
1973    
1974            int32_t iDiamondSize;
1975    
1976            int32_t min_dx;
1977            int32_t max_dx;
1978            int32_t min_dy;
1979            int32_t max_dy;
1980    
1981            VECTOR pmv[4];
1982            int32_t psad[4];
1983            VECTOR newMV;
1984            VECTOR backupMV;
1985            VECTOR startMV;
1986    
1987    //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1988            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
1989    
1990             int32_t threshA, threshB;
1991            int32_t iFound, bPredEq;
1992            int32_t iMinSAD, iSAD;
1993    
1994            int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1995    
1996            MainSearch8FuncPtr MainSearchPtr;
1997    
1998            /* Init variables */
1999            startMV.x = start_x;
2000            startMV.y = start_y;
2001    
2002            /* Get maximum range */
2003            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2004                              iFcode);
2005    
2006            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
2007                    min_dx = EVEN(min_dx);
2008                    max_dx = EVEN(max_dx);
2009                    min_dy = EVEN(min_dy);
2010                  max_dy = EVEN(max_dy);                  max_dy = EVEN(max_dy);
2011          }          }
2012    
2013          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
2014          bPredEq =          //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
2015                  get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
2016    
2017          if ((x == 0) && (y == 0)) {          if ((x == 0) && (y == 0)) {
2018                  threshA = 512 / 4;                  threshA = 512 / 4;
2019                  threshB = 1024 / 4;                  threshB = 1024 / 4;
2020    
2021          } else {          } else {
2022                  threshA = psad[0] / 4;  /* good estimate */                  threshA = psad[0] / 4;  /* good estimate? */
2023                  threshB = threshA + 256 / 4;                  threshB = threshA + 256 / 4;
2024                  if (threshA < 512 / 4)                  if (threshA < 512 / 4)
2025                          threshA = 512 / 4;                          threshA = 512 / 4;
# Line 1728  Line 2041 
2041    
2042  // Prepare for main loop  // Prepare for main loop
2043    
2044  //  if (MotionFlags & PMV_USESQUARES8)    if (MotionFlags & PMV_USESQUARES8)
2045  //      MainSearchPtr = Square8_MainSearch;        MainSearchPtr = Square8_MainSearch;
2046  //  else    else
2047    
2048          if (MotionFlags & PMV_ADVANCEDDIAMOND8)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2049                  MainSearchPtr = AdvDiamond8_MainSearch;                  MainSearchPtr = AdvDiamond8_MainSearch;
# Line 1745  Line 2058 
2058                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2059                                                  iEdgedWidth), iEdgedWidth);                                                  iEdgedWidth), iEdgedWidth);
2060          iMinSAD +=          iMinSAD +=
2061                  calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2062                                           (uint8_t) iFcode, iQuant);                                           (uint8_t) iFcode, iQuant);
2063    
2064          if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))          if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
2065                                                                  && ((uint32_t) iMinSAD <                                                                  && ((int32_t) iMinSAD <
2066                                                                          prevMB->sad8[iSubBlock]))) {                                                                          prevMB->sad8[iSubBlock]))) {
2067                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2068                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
# Line 1788  Line 2101 
2101  // the median prediction might be even better than mv16  // the median prediction might be even better than mv16
2102    
2103          if (!MVequal(pmv[0], startMV))          if (!MVequal(pmv[0], startMV))
2104                  CHECK_MV8_CANDIDATE(pmv[0].x, pmv[0].y);                  CHECK_MV8_CANDIDATE(center_x, center_y);
2105    
2106  // (0,0) if needed  // (0,0) if needed
2107          if (!MVzero(pmv[0]))          if (!MVzero(pmv[0]))
# Line 1804  Line 2117 
2117    
2118          if ((iMinSAD <= threshA) ||          if ((iMinSAD <= threshA) ||
2119                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2120                   ((uint32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {                   ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2121                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2122                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2123                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1863  Line 2176 
2176    
2177          if ((iMinSAD <= threshA) ||          if ((iMinSAD <= threshA) ||
2178                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2179                   ((uint32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {                   ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2180                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2181                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2182                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1885  Line 2198 
2198  /* 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 */
2199          iSAD =          iSAD =
2200                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2201                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2202                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2203                                                    iQuant, iFound);                                                    iQuant, iFound);
2204    
# Line 1900  Line 2213 
2213                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
2214                          iSAD =                          iSAD =
2215                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2216                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2217                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2218                                                                    iDiamondSize, iFcode, iQuant, iFound);                                                                    iDiamondSize, iFcode, iQuant, iFound);
2219    
# Line 1913  Line 2226 
2226                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2227                          iSAD =                          iSAD =
2228                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2229                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2230                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2231                                                                    iQuant, iFound);                                                                    iQuant, iFound);
2232    
# Line 1932  Line 2245 
2245          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2246                  iMinSAD =                  iMinSAD =
2247                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2248                                                          iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2249                                                          iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2250    
2251    
2252    PMVfast8_Terminate_without_Refine:    PMVfast8_Terminate_without_Refine:
2253          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2254          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2255    
2256          return iMinSAD;          return iMinSAD;
2257  }  }
# Line 1951  Line 2264 
2264                           const IMAGE * const pCur,                           const IMAGE * const pCur,
2265                           const int x,                           const int x,
2266                           const int y,                           const int y,
2267                            const int start_x,
2268                            const int start_y,
2269                            const int center_x,
2270                            const int center_y,
2271                           const uint32_t MotionFlags,                           const uint32_t MotionFlags,
2272                           const uint32_t iQuant,                           const uint32_t iQuant,
2273                           const uint32_t iFcode,                           const uint32_t iFcode,
# Line 1986  Line 2303 
2303          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2304          MACROBLOCK *oldMB = NULL;          MACROBLOCK *oldMB = NULL;
2305    
2306          static int32_t thresh2;           int32_t thresh2;
2307          int32_t bPredEq;          int32_t bPredEq;
2308          int32_t iMinSAD, iSAD = 9999;          int32_t iMinSAD, iSAD = 9999;
2309    
# Line 2009  Line 2326 
2326                  max_dy = EVEN(max_dy);                  max_dy = EVEN(max_dy);
2327          }          }
2328          /* 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; */
2329          bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2330            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_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv[0].x, pmv[0].y, psad);
2613            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2614    
2615    
2616  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 2322  Line 2645 
2645                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2646                                                  iEdgedWidth), iEdgedWidth);                                                  iEdgedWidth), iEdgedWidth);
2647          iMinSAD +=          iMinSAD +=
2648                  calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2649                                           (uint8_t) iFcode, iQuant);                                           (uint8_t) iFcode, iQuant);
2650    
2651    
# Line 2398  Line 2721 
2721    
2722  // there is no EPZS^2 for inter4v at the moment  // there is no EPZS^2 for inter4v at the moment
2723    
2724  //  if (MotionFlags & PMV_USESQUARES8)    if (MotionFlags & PMV_USESQUARES8)
2725  //      MainSearchPtr = Square8_MainSearch;        MainSearchPtr = Square8_MainSearch;
2726  //  else    else
2727    
2728          if (MotionFlags & PMV_ADVANCEDDIAMOND8)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2729                  MainSearchPtr = AdvDiamond8_MainSearch;                  MainSearchPtr = AdvDiamond8_MainSearch;
# Line 2409  Line 2732 
2732    
2733          iSAD =          iSAD =
2734                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2735                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2736                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2737                                                    iQuant, 0);                                                    iQuant, 0);
2738    
# Line 2425  Line 2748 
2748                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
2749                          iSAD =                          iSAD =
2750                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2751                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2752                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2753                                                                    iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2754    
# Line 2438  Line 2761 
2761                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2762                          iSAD =                          iSAD =
2763                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2764                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2765                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2766                                                                    iQuant, 0);                                                                    iQuant, 0);
2767    
# Line 2455  Line 2778 
2778          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2779                  iMinSAD =                  iMinSAD =
2780                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2781                                                          iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2782                                                          iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2783    
2784    EPZS8_Terminate_without_Refine:    EPZS8_Terminate_without_Refine:
2785    
2786          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2787          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2788          return iMinSAD;          return iMinSAD;
2789  }  }
2790    
2791    
2792    
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    
2839            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2840            MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2841    
2842            int32_t threshA, threshB;
2843            int32_t bPredEq;
2844            int32_t iMinSAD, iSAD;
2845    
2846    
2847    /* Get maximum range */
2848            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2849                              iFcode);
2850    
2851    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2852    
2853            if ((x == 0) && (y == 0)) {
2854                    threshA = 512;
2855                    threshB = 1024;
2856    
2857                    bPredEq = 0;
2858                    psad[0] = psad[1] = psad[2] = psad[3] = 0;
2859                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2860    
2861            } else {
2862    
2863                    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 < 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    
3000    /************ (Diamond Search)  **************/
3001    /*
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 (MotionFlags & PMV_EXTSEARCH16) {
3033    /* extended: search (up to) two more times: orignal prediction and (0,0) */
3034    
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    PMVfastInt16_Terminate_without_Refine:
3080            currPMV->x = currMV->x - center_x;
3081            currPMV->y = currMV->y - center_y;
3082            return iMinSAD;
3083    }
3084    
3085    
3086    
3087  /* ***********************************************************  /* ***********************************************************
3088          bvop motion estimation          bvop motion estimation
 // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)  
3089  ***************************************************************/  ***************************************************************/
3090    
   
3091  void  void
3092  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
3093                                           FRAMEINFO * const frame,                                           FRAMEINFO * const frame,
3094                                             const int32_t time_bp,
3095                                             const int32_t time_pp,
3096                                           // forward (past) reference                                           // forward (past) reference
3097                                           const MACROBLOCK * const f_mbs,                                           const MACROBLOCK * const f_mbs,
3098                                           const IMAGE * const f_ref,                                           const IMAGE * const f_ref,
# Line 2491  Line 3106 
3106                                           const IMAGE * const b_refV,                                           const IMAGE * const b_refV,
3107                                           const IMAGE * const b_refHV)                                           const IMAGE * const b_refHV)
3108  {  {
3109          const uint32_t mb_width = pParam->mb_width;          const int mb_width = pParam->mb_width;
3110          const uint32_t mb_height = pParam->mb_height;          const int mb_height = pParam->mb_height;
3111          const int32_t edged_width = pParam->edged_width;          const int edged_width = pParam->edged_width;
3112    
3113          uint32_t i, j;          const int32_t iWidth = pParam->width;
3114            const int32_t iHeight = pParam->height;
3115          int32_t f_sad16;  
3116          int32_t b_sad16;          int i, j, k;
3117          int32_t i_sad16;  
3118          int32_t d_sad16;          static const VECTOR zeroMV={0,0};
3119          int32_t best_sad;  
3120            int f_sad16;    /* forward (as usual) search */
3121            int b_sad16;    /* backward (only in b-frames) search */
3122            int i_sad16;    /* interpolated (both direction, b-frames only) */
3123            int d_sad16;    /* direct mode (assume almost linear motion) */
3124    
3125            int best_sad;
3126    
3127            VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
3128            VECTOR f_interpolMV, b_interpolMV;
3129          VECTOR pmv_dontcare;          VECTOR pmv_dontcare;
3130    
3131            int min_dx, max_dx, min_dy, max_dy;
3132            int f_min_dx, f_max_dx, f_min_dy, f_max_dy;
3133            int b_min_dx, b_max_dx, b_min_dy, b_max_dy;
3134    
3135            int f_count=0;
3136            int b_count=0;
3137            int i_count=0;
3138            int d_count=0;
3139    
3140            const int64_t TRB = (int32_t)time_pp - (int32_t)time_bp;
3141        const int64_t TRD = (int32_t)time_pp;
3142    
3143            // fprintf(stderr,"TRB = %lld  TRD = %lld  time_bp =%d time_pp =%d\n\n",TRB,TRD,time_bp,time_pp);
3144          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
3145          for (j = 0; j < mb_height; j++) {          for (j = 0; j < mb_height; j++) {
3146    
3147                    f_predMV = zeroMV;      /* prediction is reset at left boundary */
3148                    b_predMV = zeroMV;
3149    
3150                  for (i = 0; i < mb_width; i++) {                  for (i = 0; i < mb_width; i++) {
3151                          MACROBLOCK *mb = &frame->mbs[i + j * mb_width];                          MACROBLOCK *mb = &frame->mbs[i + j * mb_width];
3152                          const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width];                          const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width];
3153                          const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width];                          const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width];
3154    
3155                            mb->deltamv=zeroMV;
3156    
3157    /* special case, if collocated block is SKIPed: encoding is forward (0,0), cpb=0 without further ado */
3158    
3159                          if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&                          if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
3160                                  b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {                                  b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {
3161                                  mb->mode = MODE_NOT_CODED;                                  mb->mode = MODE_NOT_CODED;
3162                                  mb->mvs[0].x = 0;                                  mb->b_mvs[0] = mb->mvs[0] = zeroMV;
                                 mb->mvs[0].y = 0;  
                                 mb->b_mvs[0].x = 0;  
                                 mb->b_mvs[0].y = 0;  
3163                                  continue;                                  continue;
3164                          }                          }
                 /* force F_SAD16  
                         f_sad16 = 100;  
                         b_sad16 = 65535;  
3165    
3166                          mb->mode = MODE_FORWARD;                          if (b_mb->mode == MODE_INTER4V)
3167                          mb->mvs[0].x = 1;                          {
3168                          mb->mvs[0].y = 1;                                  d_sad16 = 0;
3169                          mb->b_mvs[0].x = 1;                          /* same method of scaling as in decoder.c, so we copy from there */
3170                          mb->b_mvs[0].y = 1;                      for (k = 0; k < 4; k++) {
3171                          continue;  
3172                   ^^ force F_SAD16 */                                          mb->directmv[k] = b_mb->mvs[k];
3173    
3174                                            mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3175                        mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3176                                                                                    ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3177                                                : mb->mvs[k].x - mb->directmv[k].x);
3178    
3179                        mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3180                            mb->b_mvs[k].y = (int32_t) ((mb->deltamv.y == 0)
3181                                                                                    ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3182                                                : mb->mvs[k].y - mb->directmv[k].y);
3183    
3184                                            d_sad16 +=
3185                                                    sad8bi(frame->image.y + (2*i+(k&1))*8 + (2*j+(k>>1))*8*edged_width,
3186                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3187                                                                    (2*i+(k&1)), (2*j+(k>>1)), 8, &mb->mvs[k], edged_width),
3188                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3189                                                                    (2*i+(k&1)), (2*j+(k>>1)), 8, &mb->b_mvs[k], edged_width),
3190                                                      edged_width);
3191                                    }
3192                            }
3193                            else
3194                            {
3195                                    mb->directmv[3] = mb->directmv[2] = mb->directmv[1] =
3196                                            mb->directmv[0] = b_mb->mvs[0];
3197    
3198                                    mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3199                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3200                                                                            ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3201                                        : mb->mvs[0].x - mb->directmv[0].x);
3202    
3203                        mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3204                    mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
3205                                                                            ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3206                                        : mb->mvs[0].y - mb->directmv[0].y);
3207    
3208                                    d_sad16 = sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3209                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3210                                                                    i, j, 16, &mb->mvs[0], edged_width),
3211                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3212                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
3213                                                      edged_width);
3214    
3215                }
3216                        d_sad16 += calc_delta_16(mb->deltamv.x, mb->deltamv.y, 1, frame->quant);
3217    
3218                          // forward search                          // forward search
3219                          f_sad16 =                          f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3220                                  SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                                  &frame->image, i, j,
3221                                                   &frame->image, i, j, frame->motion_flags,                                                  mb->mvs[0].x, mb->mvs[0].y,                     /* start point f_directMV */
3222                                                    f_predMV.x, f_predMV.y,                         /* center is f-prediction */
3223                                                    frame->motion_flags,
3224                                                   frame->quant, frame->fcode, pParam,                                                   frame->quant, frame->fcode, pParam,
3225                                                   f_mbs,  f_mbs, /* todo */                                                  f_mbs, f_mbs,
3226                                                   &mb->mvs[0], &pmv_dontcare);   // ignore pmv                                                  &mb->mvs[0], &pmv_dontcare);
3227    
3228    
3229                          // backward search                          // backward search
3230                          b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                          b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3231                                                  &frame->image, i, j, frame->motion_flags,                                                  &frame->image, i, j,
3232                                                    mb->b_mvs[0].x, mb->b_mvs[0].y,         /* start point b_directMV */
3233                                                    b_predMV.x, b_predMV.y,                         /* center is b-prediction */
3234                                                    frame->motion_flags,
3235                                                  frame->quant, frame->bcode, pParam,                                                  frame->quant, frame->bcode, pParam,
3236                                                  b_mbs, b_mbs,   /* todo */                                                  b_mbs, b_mbs,
3237                                                  &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv                                                  &mb->b_mvs[0], &pmv_dontcare);
3238    
                         // interpolate search (simple, but effective)  
                         i_sad16 = 65535;  
   
                         /*  
                         x/y range somewhat buggy  
3239                          i_sad16 =                          i_sad16 =
3240                                  sad16bi_c(frame->image.y + i * 16 + j * 16 * edged_width,                                  sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3241                                                    get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                                    get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3242                                                                    i, j, 16, mb->mvs[0].x, mb->mvs[0].y,                                                                  i, j, 16, &mb->mvs[0], edged_width),
3243                                                                    edged_width), get_ref(b_ref->y, b_refH->y,                                                    get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3244                                                                                                                  b_refV->y, b_refHV->y,                                                                  i, j, 16, &mb->b_mvs[0], edged_width),
                                                                                                                 i, j, 16,  
                                                                                                                 mb->b_mvs[0].x,  
                                                                                                                 mb->b_mvs[0].x,  
                                                                                                                 edged_width),  
3245                                                    edged_width);                                                    edged_width);
3246                          */                      i_sad16 += calc_delta_16(mb->mvs[0].x-f_predMV.x, mb->mvs[0].y-f_predMV.y,
3247                                                                    frame->fcode, frame->quant);
3248                          // TODO: direct search                      i_sad16 += calc_delta_16(mb->b_mvs[0].x-b_predMV.x, mb->b_mvs[0].y-b_predMV.y,
3249                          // predictor + range of [-32,32]                                                                  frame->bcode, frame->quant);
3250                          d_sad16 = 65535;  
3251                            get_range(&f_min_dx, &f_max_dx, &f_min_dy, &f_max_dy, i, j, 16, iWidth, iHeight,
3252                              frame->fcode);
3253                            get_range(&b_min_dx, &b_max_dx, &b_min_dy, &b_max_dy, i, j, 16, iWidth, iHeight,
3254                              frame->bcode);
3255    
3256    /* Interpolated MC motion vector search, this is tedious and more complicated because there are
3257       two values for everything, always one for backward and one for forward ME. Still, we don't gain
3258       much from this search, maybe it should simply be skipped and simply current i_sad16 value used
3259       as "optimal". */
3260    
3261                            i_sad16 = Diamond16_InterpolMainSearch(
3262                                                    f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3263                                                    frame->image.y + i * 16 + j * 16 * edged_width,
3264                                                    b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3265                                                    i, j,
3266                                                    mb->mvs[0].x, mb->mvs[0].y,
3267                                                    mb->b_mvs[0].x, mb->b_mvs[0].y,
3268                                                    i_sad16,
3269                                                    &f_interpolMV, &b_interpolMV,
3270                                                    f_predMV.x, f_predMV.y, b_predMV.x, b_predMV.y,
3271                                                    f_min_dx, f_max_dx, f_min_dy, f_max_dy,
3272                                                    b_min_dx, b_max_dx, b_min_dy, b_max_dy,
3273                                                    edged_width,  2,
3274                                                    frame->fcode, frame->bcode,frame->quant,0);
3275    
3276                            i_sad16 = Diamond16_InterpolMainSearch(
3277                                                    f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3278                                                    frame->image.y + i * 16 + j * 16 * edged_width,
3279                                                    b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3280                                                    i, j,
3281                                                    f_interpolMV.x, f_interpolMV.y,
3282                                                    b_interpolMV.x, b_interpolMV.y,
3283                                                    i_sad16,
3284                                                    &f_interpolMV, &b_interpolMV,
3285                                                    f_predMV.x, f_predMV.y, b_predMV.x, b_predMV.y,
3286                                                    f_min_dx, f_max_dx, f_min_dy, f_max_dy,
3287                                                    b_min_dx, b_max_dx, b_min_dy, b_max_dy,
3288                                                    edged_width,  1,
3289                                                    frame->fcode, frame->bcode,frame->quant,0);             // equiv to halfpel refine
3290    
3291    
3292    /*  DIRECT MODE DELTA VECTOR SEARCH.
3293        This has to be made more effective, but at the moment I'm happy it's running at all */
3294    
3295    /* There are two range restrictions for direct mode: deltaMV is limited to [-32,31] in halfpel units, and
3296       absolute vector must not lie outside of image dimensions. Constraint one is dealt with by CHECK_MV16_DIRECT
3297       and for constraint two we need distance to boundary. This is done by get_range very large fcode (hack!) */
3298    
3299                            get_range(&min_dx, &max_dx, &min_dy, &max_dy, i, j, 16, iWidth, iHeight, 19);
3300    
3301                            d_sad16 = Diamond16_DirectMainSearch(
3302                                                    f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3303                                                    frame->image.y + i*16 + j*16*edged_width,
3304                                                    b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3305                                                    i, j,
3306                                                    TRB,TRD,
3307                                                    0,0,
3308                                                    d_sad16,
3309                                                    &mb->deltamv,
3310                                                    mb->directmv, // this has to be pre-initialized with b_mb->mvs[]
3311                                            min_dx, max_dx, min_dy, max_dy,
3312                                                    edged_width, 2, frame->quant, 0);
3313    
3314                            d_sad16 = Diamond16_DirectMainSearch(
3315                                                    f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3316                                                    frame->image.y + i*16 + j*16*edged_width,
3317                                                    b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3318                                                    i, j,
3319                                                    TRB,TRD,
3320                                                    mb->deltamv.x, mb->deltamv.y,
3321                                                    d_sad16,
3322                                                    &mb->deltamv,
3323                                                    mb->directmv, // this has to be pre-initialized with b_mb->mvs[]
3324                                            min_dx, max_dx, min_dy, max_dy,
3325                                                    edged_width, 1, frame->quant, 0);               // equiv to halfpel refine
3326    
3327    
3328    //                      i_sad16 = 65535;                /* remove the comment to disable any of the MODEs */
3329    //                      f_sad16 = 65535;
3330    //                      b_sad16 = 65535;
3331    //                      d_sad16 = 65535;
3332    
3333                          if (f_sad16 < b_sad16) {                          if (f_sad16 < b_sad16) {
3334                                  best_sad = f_sad16;                                  best_sad = f_sad16;
# Line 2586  Line 3344 
3344                          }                          }
3345    
3346                          if (d_sad16 < best_sad) {                          if (d_sad16 < best_sad) {
3347    
3348                                    if (b_mb->mode == MODE_INTER4V)
3349                                    {
3350    
3351                                    /* how to calc vectors is defined in standard. mvs[] and b_mvs[] are only for motion compensation */
3352                                    /* for the bitstream, the value mb->deltamv is read directly */
3353    
3354                                for (k = 0; k < 4; k++) {
3355    
3356                                                    mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3357                                mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3358                                                                                            ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3359                                                        : mb->mvs[k].x - mb->directmv[k].x);
3360    
3361                                mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3362                            mb->b_mvs[k].y = (int32_t) ((mb->deltamv.y == 0)
3363                                                                                            ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3364                                                : mb->mvs[k].y - mb->directmv[k].y);
3365                                            }
3366                                    }
3367                                    else
3368                                    {
3369                                            mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3370    
3371                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3372                                                                                    ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3373                                            : mb->mvs[0].x - mb->directmv[0].x);
3374    
3375                                mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3376    
3377                            mb->b_mvs[0].y = (int32_t) ((mb->deltamv.y == 0)
3378                                                                                    ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3379                                                : mb->mvs[0].y - mb->directmv[0].y);
3380    
3381                                            mb->mvs[3] = mb->mvs[2] = mb->mvs[1] = mb->mvs[0];
3382                                            mb->b_mvs[3] = mb->b_mvs[2] = mb->b_mvs[1] = mb->b_mvs[0];
3383                    }
3384    
3385                                  best_sad = d_sad16;                                  best_sad = d_sad16;
3386                                  mb->mode = MODE_DIRECT;                                  mb->mode = MODE_DIRECT;
3387                          }                          }
3388    
3389                            switch (mb->mode)
3390                            {
3391                                    case MODE_FORWARD:
3392                                            f_count++;
3393                                            f_predMV = mb->mvs[0];
3394                                            break;
3395                                    case MODE_BACKWARD:
3396                                            b_count++;
3397                                            b_predMV = mb->b_mvs[0];
3398    
3399                                            break;
3400                                    case MODE_INTERPOLATE:
3401                                            i_count++;
3402                                            mb->mvs[0] = f_interpolMV;
3403                                            mb->b_mvs[0] = b_interpolMV;
3404                                            f_predMV = mb->mvs[0];
3405                                            b_predMV = mb->b_mvs[0];
3406                                            break;
3407                                    case MODE_DIRECT:
3408                                            d_count++;
3409                                            break;
3410                                    default:
3411                                            break;
3412                            }
3413    
3414                  }                  }
3415          }          }
3416    
3417    #ifdef _DEBUG_BFRAME_STAT
3418            fprintf(stderr,"B-Stat: F: %04d   B: %04d   I: %04d  D: %04d\n",
3419                                    f_count,b_count,i_count,d_count);
3420    #endif
3421    
3422  }  }

Legend:
Removed from v.252  
changed lines
  Added in v.430

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