[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 181, Wed May 22 12:42:25 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), (int)(1.49591+0.5), (int)(1.68601+0.5),  { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),
52          (int)(1.89187+0.5), (int)(2.11542+0.5), (int)(2.35878+0.5), (int)(2.62429+0.5), (int)(2.91455+0.5),                  (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),
53          (int)(3.23253+0.5), (int)(3.58158+0.5), (int)(3.96555+0.5), (int)(4.38887+0.5), (int)(4.85673+0.5),          (int) (1.89187 + 0.5), (int) (2.11542 + 0.5), (int) (2.35878 + 0.5),
54          (int)(5.37519+0.5), (int)(5.95144+0.5), (int)(6.59408+0.5), (int)(7.31349+0.5), (int)(8.12242+0.5),                  (int) (2.62429 + 0.5), (int) (2.91455 + 0.5),
55          (int)(9.03669+0.5), (int)(10.0763+0.5), (int)(11.2669+0.5), (int)(12.6426+0.5), (int)(14.2493+0.5),          (int) (3.23253 + 0.5), (int) (3.58158 + 0.5), (int) (3.96555 + 0.5),
56          (int)(16.1512+0.5), (int)(18.442+0.5),  (int)(21.2656+0.5), (int)(24.8580+0.5), (int)(29.6436+0.5),                  (int) (4.38887 + 0.5), (int) (4.85673 + 0.5),
57          (int)(36.4949+0.5)      };          (int) (5.37519 + 0.5), (int) (5.95144 + 0.5), (int) (6.59408 + 0.5),
58                    (int) (7.31349 + 0.5), (int) (8.12242 + 0.5),
59            (int) (9.03669 + 0.5), (int) (10.0763 + 0.5), (int) (11.2669 + 0.5),
60                    (int) (12.6426 + 0.5), (int) (14.2493 + 0.5),
61            (int) (16.1512 + 0.5), (int) (18.442 + 0.5), (int) (21.2656 + 0.5),
62                    (int) (24.8580 + 0.5), (int) (29.6436 + 0.5),
63            (int) (36.4949 + 0.5)
64    };
65    
66  static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now*/  static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now*/
67    
# Line 212  Line 76 
76  };  };
77    
78    
79  static __inline uint32_t mv_bits(int32_t component, const uint32_t iFcode)  static __inline uint32_t
80    mv_bits(int32_t component,
81                    const uint32_t iFcode)
82  {  {
83      if (component == 0)      if (component == 0)
84                  return 1;                  return 1;
# Line 220  Line 86 
86      if (component < 0)      if (component < 0)
87                  component = -component;                  component = -component;
88    
89      if (iFcode == 1)          if (iFcode == 1) {
     {  
90                  if (component > 32)                  if (component > 32)
91                      component = 32;                      component = 32;
92    
# Line 238  Line 103 
103  }  }
104    
105    
106  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)  static __inline uint32_t
107    calc_delta_16(const int32_t dx,
108                              const int32_t dy,
109                              const uint32_t iFcode,
110                              const uint32_t iQuant)
111  {  {
112          return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));          return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) +
113                                                                                                              mv_bits(dy, iFcode));
114  }  }
115    
116  static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)  static __inline uint32_t
117    calc_delta_8(const int32_t dx,
118                             const int32_t dy,
119                             const uint32_t iFcode,
120                             const uint32_t iQuant)
121  {  {
122      return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));          return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) +
123                                                                                                       mv_bits(dy, iFcode));
124  }  }
125    
126    bool
127    MotionEstimation(MBParam * const pParam,
   
   
 #ifndef SEARCH16  
 #define SEARCH16        PMVfastSearch16  
 //#define SEARCH16      FullSearch16  
 //#define SEARCH16      EPZSSearch16  
 #endif  
   
 #ifndef SEARCH8  
 #define SEARCH8         PMVfastSearch8  
 //#define SEARCH8       EPZSSearch8  
 #endif  
   
 bool MotionEstimation(  
         MBParam * const pParam,  
128          FRAMEINFO * const current,          FRAMEINFO * const current,
129          FRAMEINFO * const reference,          FRAMEINFO * const reference,
130          const IMAGE * const pRefH,          const IMAGE * const pRefH,
131          const IMAGE * const pRefV,          const IMAGE * const pRefV,
132          const IMAGE * const pRefHV,          const IMAGE * const pRefHV,
133          const uint32_t iLimit)          const uint32_t iLimit)
   
134  {  {
135          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
136          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
137          MACROBLOCK * const pMBs = current->mbs;          MACROBLOCK * const pMBs = current->mbs;
138          MACROBLOCK * const prevMBs = reference->mbs;    // previous frame          MACROBLOCK *const prevMBs = reference->mbs;
   
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 291  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                          pMB->sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          if (pMB->mode == MODE_NOT_CODED)
158                                           x, y, current->motion_flags, current->quant, current->fcode,                                  continue;
                                          pParam, pMBs, prevMBs, &pMB->mv16, &pMB->pmvs[0]);  
159    
160                            predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
161    
162                          if (0 < (pMB->sad16 - MV16_INTER_BIAS))                          pMB->sad16 =
163                          {                                  SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
164                                                     x, y, predMV.x, predMV.y, predMV.x, predMV.y,
165                                                     current->motion_flags, current->quant,
166                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
167                                                     &pMB->pmvs[0]);
168    
169                            if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
170                                  int32_t deviation;                                  int32_t deviation;
171                                  deviation = dev16(pCurrent->y + x*16 + y*16*pParam->edged_width,  
172                                    deviation =
173                                            dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
174                                                           pParam->edged_width);                                                           pParam->edged_width);
175    
176                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS))                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
                                 {  
177                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
178                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
179                                                                   = pMB->mvs[2] = pMB->mvs[3] = zeroMV;                                                  pMB->mvs[3] = zeroMV;
180                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1]                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
181                                                               = pMB->sad8[2] = pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
182    
183                                          iIntra++;                                          iIntra++;
184                                          if (iIntra >= iLimit)                                          if (iIntra >= iLimit)
# Line 322  Line 187 
187                                          continue;                                          continue;
188                                  }                                  }
189                          }                          }
                         pMB->mode = MODE_INTER;  
                         pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;  
            pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = pMB->sad16;  
                 }  
   
         // we try to do as few INTER4V-searches as possible. So we split ME in two parts, normal  
         // SEARCH16 and only for special blocks SEARCH8. May this should be modified for quality  
         // levels.  
   
   
190    
191                            pmv = pMB->pmvs[0];
192          if (current->global_flags & XVID_INTER4V)          if (current->global_flags & XVID_INTER4V)
193                  for (y = 0; y < iHcount; y++)                                  if ((!(current->global_flags & XVID_LUMIMASKING) ||
194                          for (x = 0; x < iWcount; x++)                                           pMB->dquant == NO_CHANGE)) {
                         {  
                                 MACROBLOCK* const pMB = &pMBs[x + y * iWcount];  
   
                                 if (pMB->mode == MODE_INTRA)  
                                         continue;  
   
   
                                 if ( (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE) )  
                                 {  
                                 int32_t neigh=0;  
   
                                 if (x>0)  
                                 {       neigh += abs((pMB->mv16.x)-((pMB-1)->mv16.x));  
                                         neigh += abs((pMB->mv16.y)-((pMB-1)->mv16.y));  
                                 }  
                                 if (y>0)  
                                 {       neigh += abs((pMB->mv16.x)-((pMB-iWcount)->mv16.x));  
                                         neigh += abs((pMB->mv16.y)-((pMB-iWcount)->mv16.y));  
                                 }  
                                 if (x<(iWcount-1))  
                                 {       neigh += abs((pMB->mv16.x)-((pMB+1)->mv16.x));  
                                         neigh += abs((pMB->mv16.y)-((pMB+1)->mv16.y));  
                                 }  
                                 if (y<(iHcount-1))  
                                 {       neigh += abs((pMB->mv16.x)-((pMB+iHcount)->mv16.x));  
                                         neigh += abs((pMB->mv16.y)-((pMB+iHcount)->mv16.y));  
                                 }  
   
                                 if (neigh > NEIGH_MOVE_THRESH)  
                                 {  
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, pCurrent,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
200                                                                 2*x, 2*y, pMB->mv16.x, pMB->mv16.y,                                                                          pCurrent, 2 * x, 2 * y,
201                                                                     current->motion_flags, current->quant, current->fcode,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
202                                                                 pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);                                                                          current->motion_flags,
203                                                                            current->quant, current->fcode, pParam,
204                                          if (sad8 < pMB->sad16)                                                                          pMBs, prevMBs, &pMB->mvs[0],
205                                          sad8 += pMB->sad8[1]                                                                          &pMB->pmvs[0]);
206                                                  = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                          }
207                                         2*x+1, 2*y, pMB->mv16.x, pMB->mv16.y,                                          if (sad8 < pMB->sad16) {
208                                                          current->motion_flags, current->quant, current->fcode,  
209                                                          pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);                                                  predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
210                                                    sad8 += pMB->sad8[1] =
211                                          if (sad8 < pMB->sad16)                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
212                                          sad8 += pMB->sad8[2]                                                                          pCurrent, 2 * x + 1, 2 * y,
213                                                  = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
214                                                          2*x, 2*y+1, pMB->mv16.x, pMB->mv16.y,                                                                          current->motion_flags,
215                                                          current->motion_flags, current->quant, current->fcode,                                                                          current->quant, current->fcode, pParam,
216                                                          pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);                                                                          pMBs, prevMBs, &pMB->mvs[1],
217                                                                            &pMB->pmvs[1]);
218                                          if (sad8 < pMB->sad16)                                          }
219                                          sad8 += pMB->sad8[3]                                          if (sad8 < pMB->sad16) {
220                                                  = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                  predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
221                                                          2*x+1, 2*y+1, pMB->mv16.x, pMB->mv16.y,                                                  sad8 += pMB->sad8[2] =
222                                                          current->motion_flags, current->quant, current->fcode,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
223                                                          pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);                                                                          pCurrent, 2 * x, 2 * y + 1,
224                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
225                                                                            current->motion_flags,
226                                                                            current->quant, current->fcode, pParam,
227                                                                            pMBs, prevMBs, &pMB->mvs[2],
228                                                                            &pMB->pmvs[2]);
229                                            }
230                                            if (sad8 < pMB->sad16) {
231                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
232                                                    sad8 += pMB->sad8[3] =
233                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
234                                                                            pCurrent, 2 * x + 1, 2 * y + 1,
235                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
236                                                                            current->motion_flags,
237                                                                            current->quant, current->fcode, pParam,
238                                                                            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
245                          */                          */
246    
247                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16) {
                                         {  
248                                                  pMB->mode = MODE_INTER4V;                                                  pMB->mode = MODE_INTER4V;
249                        pMB->sad8[0] *= 4;                        pMB->sad8[0] *= 4;
250                                                  pMB->sad8[1] *= 4;                                                  pMB->sad8[1] *= 4;
# Line 410  Line 253 
253                                                  continue;                                                  continue;
254                                          }                                          }
255    
                                         pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;  
256                                  }                                  }
257    
258                            pMB->mode = MODE_INTER;
259                            pMB->pmvs[0] = pmv;     /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
260                            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] =
262                                    pMB->sad16;
263                                  }                                  }
   
                 // get_pmv has to be called again, because inter4v changes predictors  
   
                         pmv = get_pmv(pMBs, x, y, pParam->mb_width, 0);  
                         pMB->pmvs[0].x = pMB->mv16.x - pmv.x;   /* the other pmvs are only needed in INTER4V-mode */  
                         pMB->pmvs[0].y = pMB->mv16.y - pmv.y;  
   
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 448  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 458  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 468  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 476  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 484  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 494  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 504  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 514  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 540  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 552  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    
402  }  }
403  */  */
404    
405  int32_t Diamond16_MainSearch(  int32_t
406          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
407          const uint8_t * const pRefH,          const uint8_t * const pRefH,
408          const uint8_t * const pRefV,          const uint8_t * const pRefV,
409          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
410          const uint8_t * const cur,          const uint8_t * const cur,
411          const int x, const int y,                                           const int x,
412          int32_t startx, int32_t starty,                                           const int y,
413          int32_t iMinSAD,                                     const int start_x,
414                                       const int start_y,
415                                       int iMinSAD,
416          VECTOR * const currMV,          VECTOR * const currMV,
417          const VECTOR * const pmv,                                     const int center_x,
418          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
419          const int32_t min_dy, const int32_t max_dy,                                           const int32_t min_dx,
420                                             const int32_t max_dx,
421                                             const int32_t min_dy,
422                                             const int32_t max_dy,
423          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
424          const int32_t iDiamondSize,          const int32_t iDiamondSize,
425          const int32_t iFcode,          const int32_t iFcode,
# Line 582  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          backupMV.x = startx;  
436          backupMV.y = starty;          backupMV.x = start_x;
437            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 594  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,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
454                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
455                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
456                          if ( iDirection != 4)                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
457                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                     backupMV.y, 2);
458                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
459                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
460                  }                                                                                     backupMV.y - iDiamondSize, 3);
461          else                          if (iDirectionBackup != 3)
462          {                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
463                  currMV->x = startx;                                                                                     backupMV.y + iDiamondSize, 4);
464                  currMV->y = starty;                  }
465            } else {
466                    currMV->x = start_x;
467                    currMV->y = start_y;
468          }          }
469          return iMinSAD;          return iMinSAD;
470  }  }
471    
472  int32_t Square16_MainSearch(  int32_t
473                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
474                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
475                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
476                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
477                                          const uint8_t * const cur,                                          const uint8_t * const cur,
478                                          const int x, const int y,                                          const int x,
479                                          int32_t startx, int32_t starty,                                          const int y,
480                                          int32_t iMinSAD,                                     const int start_x,
481                                       const int start_y,
482                                       int iMinSAD,
483                                          VECTOR * const currMV,                                          VECTOR * const currMV,
484                                          const VECTOR * const pmv,                                     const int center_x,
485                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
486                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
487                                            const int32_t max_dx,
488                                            const int32_t min_dy,
489                                            const int32_t max_dy,
490                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
491                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
492                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 641  Line 498 
498          int32_t iDirection=0;          int32_t iDirection=0;
499          int32_t iSAD;          int32_t iSAD;
500          VECTOR backupMV;          VECTOR backupMV;
501          backupMV.x = startx;  
502          backupMV.y = starty;          backupMV.x = start_x;
503            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 657  Line 515 
515          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
516          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
517    
518          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
519          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
520          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
521          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
522            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
523                                                             backupMV.y - iDiamondSize, 7);
524            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
525                                                             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;
532    
533                          switch (iDirection)                          switch (iDirection) {
                         {  
534                                  case 1:                                  case 1:
535                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
536                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
537                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
538                                                                                     backupMV.y - iDiamondSize, 5);
539                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
540                                                                                     backupMV.y - iDiamondSize, 7);
541                                          break;                                          break;
542                                  case 2:                                  case 2:
543                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
544                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
545                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
546                                                                                     backupMV.y + iDiamondSize, 6);
547                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
548                                                                                     backupMV.y + iDiamondSize, 8);
549                                          break;                                          break;
550    
551                                  case 3:                                  case 3:
552                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
553                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
554                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
555                                                                                     backupMV.y - iDiamondSize, 7);
556                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
557                                                                                     backupMV.y + iDiamondSize, 8);
558                                          break;                                          break;
559    
560                                  case 4:                                  case 4:
561                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
562                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
563                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
564                                                                                     backupMV.y - iDiamondSize, 5);
565                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
566                                                                                     backupMV.y + iDiamondSize, 6);
567                                          break;                                          break;
568    
569                                  case 5:                                  case 5:
570                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
571                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
572                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
573                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
574                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
575                                                                                     backupMV.y - iDiamondSize, 5);
576                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
577                                                                                     backupMV.y + iDiamondSize, 6);
578                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
579                                                                                     backupMV.y - iDiamondSize, 7);
580                                          break;                                          break;
581    
582                                  case 6:                                  case 6:
583                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
584                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
585                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
586                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
587                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
588                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
589                                                                                     backupMV.y - iDiamondSize, 5);
590                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
591                                                                                     backupMV.y + iDiamondSize, 6);
592                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
593                                                                                     backupMV.y + iDiamondSize, 8);
594    
595                                          break;                                          break;
596    
597                                  case 7:                                  case 7:
598                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
599                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
600                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
601                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
602                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
603                                                                                     backupMV.y - iDiamondSize, 5);
604                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
605                                                                                     backupMV.y - iDiamondSize, 7);
606                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
607                                                                                     backupMV.y + iDiamondSize, 8);
608                                          break;                                          break;
609    
610                                  case 8:                                  case 8:
611                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
612                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
613                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
614                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
615                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
616                                                                                     backupMV.y + iDiamondSize, 6);
617                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
618                                                                                     backupMV.y - iDiamondSize, 7);
619                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
620                                                                                     backupMV.y + iDiamondSize, 8);
621                                          break;                                          break;
622                          default:                          default:
623                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
624                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
625                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
626                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
627                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
628                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
629                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
630                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
631                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
632                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
633                                                                                     backupMV.y - iDiamondSize, 5);
634                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
635                                                                                     backupMV.y + iDiamondSize, 6);
636                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
637                                                                                     backupMV.y - iDiamondSize, 7);
638                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
639                                                                                     backupMV.y + iDiamondSize, 8);
640                                          break;                                          break;
641                          }                          }
642                  }                  }
643          else          } else {
644                  {                  currMV->x = start_x;
645                          currMV->x = startx;                  currMV->y = start_y;
                         currMV->y = starty;  
646                  }                  }
647          return iMinSAD;          return iMinSAD;
648  }  }
649    
650    
651  int32_t Full16_MainSearch(  int32_t
652                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
653                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
654                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
655                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
656                                          const uint8_t * const cur,                                          const uint8_t * const cur,
657                                          const int x, const int y,                                    const int x,
658                                          int32_t startx, int32_t starty,                                    const int y,
659                                          int32_t iMinSAD,                                     const int start_x,
660                                       const int start_y,
661                                       int iMinSAD,
662                                          VECTOR * const currMV,                                          VECTOR * const currMV,
663                                          const VECTOR * const pmv,                                     const int center_x,
664                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
665                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
666                                      const int32_t max_dx,
667                                      const int32_t min_dy,
668                                      const int32_t max_dy,
669                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
670                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
671                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 771  Line 675 
675          int32_t iSAD;          int32_t iSAD;
676          int32_t dx,dy;          int32_t dx,dy;
677          VECTOR backupMV;          VECTOR backupMV;
678          backupMV.x = startx;  
679          backupMV.y = starty;          backupMV.x = start_x;
680            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 781  Line 686 
686          return iMinSAD;          return iMinSAD;
687  }  }
688    
689  int32_t AdvDiamond16_MainSearch(  int32_t
690          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
691          const uint8_t * const pRefH,          const uint8_t * const pRefH,
692          const uint8_t * const pRefV,          const uint8_t * const pRefV,
693          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
694          const uint8_t * const cur,          const uint8_t * const cur,
695          const int x, const int y,                                                  const int x,
696          int32_t startx, int32_t starty,                                                  const int y,
697          int32_t iMinSAD,                                             int start_x,
698                                               int start_y,
699                                               int iMinSAD,
700          VECTOR * const currMV,          VECTOR * const currMV,
701          const VECTOR * const pmv,                                             const int center_x,
702          const int32_t min_dx, const int32_t max_dx,                                             const int center_y,
703          const int32_t min_dy, const int32_t max_dy,                                                  const int32_t min_dx,
704                                                    const int32_t max_dx,
705                                                    const int32_t min_dy,
706                                                    const int32_t max_dy,
707          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
708          const int32_t iDiamondSize,          const int32_t iDiamondSize,
709          const int32_t iFcode,          const int32_t iFcode,
# Line 805  Line 715 
715    
716  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
717    
718          if (iDirection)          if (iDirection) {
719          {                  CHECK_MV16_CANDIDATE(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+iDiamondSize, starty);                  CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
722                  CHECK_MV16_CANDIDATE(startx, starty-iDiamondSize);                  CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
723                  CHECK_MV16_CANDIDATE(startx, starty+iDiamondSize);          } else {
         }  
         else  
         {  
724                  int bDirection = 1+2+4+8;                  int bDirection = 1+2+4+8;
725                  do  
726                  {                  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 836  Line 743 
743                          {                          {
744                                  bDirection = iDirection;                                  bDirection = iDirection;
745                                  iDirection = 0;                                  iDirection = 0;
746                                  startx=currMV->x; starty=currMV->y;                                  start_x = currMV->x;
747                                    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; starty=currMV->y;                                          start_x = currMV->x;
761                                            start_y = currMV->y;
762                                  }                                  }
763                          }                          } else                          //about to quit, eh? not so fast....
                         else //about to quit, eh? not so fast....  
                         {  
                                 switch (bDirection)  
764                                  {                                  {
765                                    switch (bDirection) {
766                                  case 2:                                  case 2:
767                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
768                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                           start_y - iDiamondSize, 2 + 4);
769                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
770                                                                                             start_y + iDiamondSize, 2 + 8);
771                                          break;                                          break;
772                                  case 1:                                  case 1:
773                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);  
774                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
775                                                                                             start_y - iDiamondSize, 1 + 4);
776                                            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, starty-iDiamondSize, 1+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
781                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                                                                           start_y - iDiamondSize, 1 + 4);
782                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
783                                                                                             start_y - iDiamondSize, 2 + 4);
784                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
785                                                                                             start_y + iDiamondSize, 2 + 8);
786                                          break;                                          break;
787                                  case 4:                                  case 4:
788                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
789                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                                                                           start_y - iDiamondSize, 2 + 4);
790                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
791                                                                                             start_y - iDiamondSize, 1 + 4);
792                                          break;                                          break;
793                                  case 8:                                  case 8:
794                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
795                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                           start_y + iDiamondSize, 2 + 8);
796                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
797                                                                                             start_y + iDiamondSize, 1 + 8);
798                                          break;                                          break;
799                                  case 1+4:                                  case 1+4:
800                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
801                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                                                                           start_y + iDiamondSize, 1 + 8);
802                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
803                                                                                             start_y - iDiamondSize, 1 + 4);
804                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
805                                                                                             start_y - iDiamondSize, 2 + 4);
806                                          break;                                          break;
807                                  case 2+8:                                  case 2+8:
808                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
809                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                           start_y - iDiamondSize, 1 + 4);
810                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
811                                                                                             start_y + iDiamondSize, 1 + 8);
812                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
813                                                                                             start_y + iDiamondSize, 2 + 8);
814                                          break;                                          break;
815                                  case 1+8:                                  case 1+8:
816                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
817                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                           start_y - iDiamondSize, 2 + 4);
818                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
819                                                                                             start_y + iDiamondSize, 2 + 8);
820                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
821                                                                                             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, starty-iDiamondSize, 1+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
825                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                           start_y - iDiamondSize, 1 + 4);
826                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
827                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                           start_y + iDiamondSize, 1 + 8);
828                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
829                                                                                             start_y - iDiamondSize, 2 + 4);
830                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
831                                                                                             start_y + iDiamondSize, 2 + 8);
832                                          break;                                          break;
833                                  }                                  }
834                                  if (!iDirection) break; //ok, the end. really                                  if (!iDirection)
835                                  else                                          break;          //ok, the end. really
836                                  {       bDirection=iDirection;                                  else {
837                                          startx=currMV->x; starty=currMV->y;                                          bDirection = iDirection;
838                                            start_x = currMV->x;
839                                            start_y = currMV->y;
840                                  }                                  }
841                          }                          }
842                  }                  }
# Line 912  Line 845 
845          return iMinSAD;          return iMinSAD;
846  }  }
847    
848  int32_t AdvDiamond8_MainSearch(  #define CHECK_MV16_F_INTERPOL(X,Y) { \
849          const uint8_t * const pRef,    if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
850          const uint8_t * const pRefH,      && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
851          const uint8_t * const pRefV,    { \
852          const uint8_t * const pRefHV,      iSAD = sad16bi( cur, \
853                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
854                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
855                            iEdgedWidth); \
856        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
857        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
858        if (iSAD < iMinSAD) \
859        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); } } \
860    }
861    
862    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y) { \
863      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
864        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
865      { \
866        iSAD = sad16bi( cur, \
867                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
868                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
869                            iEdgedWidth); \
870        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
871        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
872        if (iSAD < iMinSAD) \
873        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); iFound=0;} } \
874    }
875    
876    #define CHECK_MV16_B_INTERPOL(X,Y) { \
877      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
878        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
879      { \
880        iSAD = sad16bi( cur, \
881                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
882                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
883                            iEdgedWidth); \
884        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
885        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
886        if (iSAD < iMinSAD) \
887        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); } } \
888    }
889    
890    #define CHECK_MV16_B_INTERPOL_FOUND(X,Y) { \
891      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
892        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
893      { \
894        iSAD = sad16bi( cur, \
895                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
896                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
897                            iEdgedWidth); \
898        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
899        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
900        if (iSAD < iMinSAD) \
901        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); iFound=0;} } \
902    }
903    
904    int32_t
905    Diamond16_InterpolMainSearch(
906                                            const uint8_t * const f_pRef,
907                                             const uint8_t * const f_pRefH,
908                                             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          const int x, const int y,  
913          int32_t startx, int32_t starty,                                          const uint8_t * const b_pRef,
914          int32_t iMinSAD,                                           const uint8_t * const b_pRefH,
915          VECTOR * const currMV,                                           const uint8_t * const b_pRefV,
916          const VECTOR * const pmv,                                           const uint8_t * const b_pRefHV,
917          const int32_t min_dx, const int32_t max_dx,  
918          const int32_t min_dy, const int32_t max_dy,                                           const int x,
919                                             const int y,
920    
921                                       const int f_start_x,
922                                       const int f_start_y,
923                                       const int b_start_x,
924                                       const int b_start_y,
925    
926                                       int iMinSAD,
927                                       VECTOR * const f_currMV,
928                                       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            f_currMV->x = f_start_x;
962            f_currMV->y = f_start_y;
963            b_currMV->x = b_start_x;
964            b_currMV->y = b_start_y;
965    
         if (iDirection)  
         {  
                 CHECK_MV8_CANDIDATE(startx-iDiamondSize, starty);  
                 CHECK_MV8_CANDIDATE(startx+iDiamondSize, starty);  
                 CHECK_MV8_CANDIDATE(startx, starty-iDiamondSize);  
                 CHECK_MV8_CANDIDATE(startx, starty+iDiamondSize);  
         }  
         else  
         {  
                 int bDirection = 1+2+4+8;  
966                  do                  do
967                  {                  {
968                          iDirection = 0;                  iFound = 1;
                         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)  
                                 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                                  bDirection = iDirection;          return iMinSAD;
                                 iDirection = 0;  
                                 startx=currMV->x; starty=currMV->y;  
                                 if (bDirection & 3) //our candidate is left or right  
                                 {  
                                         CHECK_MV8_CANDIDATE_DIR(startx,starty+iDiamondSize, 8);  
                                         CHECK_MV8_CANDIDATE_DIR(startx,starty-iDiamondSize, 4);  
                                 }  
                                 else // what remains here is up or down  
                                 {  
                                         CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty, 2);  
                                         CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty, 1);  
987                                  }                                  }
988    
989                                  if (iDirection)  /* Sorry, these MACROS really got too large... I'll turn them into function soon! */
990                                  {       bDirection+=iDirection;  
991                                          startx=currMV->x; starty=currMV->y;  #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                          else //about to quit, eh? not so fast....  
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;
1150                                    iDirection = 0;
1151                                    start_x = currMV->x;
1152                                    start_y = currMV->y;
1153                                    if (bDirection & 3)     //our candidate is left or right
1154                          {                          {
1155                                  switch (bDirection)                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1156                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1157                                    } else                  // what remains here is up or down
1158                                    {
1159                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1160                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1161                                    }
1162    
1163                                    if (iDirection) {
1164                                            bDirection += iDirection;
1165                                            start_x = currMV->x;
1166                                            start_y = currMV->y;
1167                                    }
1168                            } else                          //about to quit, eh? not so fast....
1169                                  {                                  {
1170                                    switch (bDirection) {
1171                                  case 2:                                  case 2:
1172                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1173                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                          start_y - iDiamondSize, 2 + 4);
1174                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1175                                                                                            start_y + iDiamondSize, 2 + 8);
1176                                          break;                                          break;
1177                                  case 1:                                  case 1:
1178                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1179                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                          start_y - iDiamondSize, 1 + 4);
1180                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1181                                                                                            start_y + iDiamondSize, 1 + 8);
1182                                          break;                                          break;
1183                                  case 2+4:                                  case 2+4:
1184                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1185                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                                                                          start_y - iDiamondSize, 1 + 4);
1186                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1187                                                                                            start_y - iDiamondSize, 2 + 4);
1188                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1189                                                                                            start_y + iDiamondSize, 2 + 8);
1190                                          break;                                          break;
1191                                  case 4:                                  case 4:
1192                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1193                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                                                                          start_y - iDiamondSize, 2 + 4);
1194                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1195                                                                                            start_y - iDiamondSize, 1 + 4);
1196                                          break;                                          break;
1197                                  case 8:                                  case 8:
1198                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1199                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                          start_y + iDiamondSize, 2 + 8);
1200                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1201                                                                                            start_y + iDiamondSize, 1 + 8);
1202                                          break;                                          break;
1203                                  case 1+4:                                  case 1+4:
1204                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1205                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                                                                          start_y + iDiamondSize, 1 + 8);
1206                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1207                                                                                            start_y - iDiamondSize, 1 + 4);
1208                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1209                                                                                            start_y - iDiamondSize, 2 + 4);
1210                                          break;                                          break;
1211                                  case 2+8:                                  case 2+8:
1212                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1213                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                          start_y - iDiamondSize, 1 + 4);
1214                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1215                                                                                            start_y + iDiamondSize, 1 + 8);
1216                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1217                                                                                            start_y + iDiamondSize, 2 + 8);
1218                                          break;                                          break;
1219                                  case 1+8:                                  case 1+8:
1220                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1221                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                          start_y - iDiamondSize, 2 + 4);
1222                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1223                                                                                            start_y + iDiamondSize, 2 + 8);
1224                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1225                                                                                            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, starty-iDiamondSize, 1+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1229                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                          start_y - iDiamondSize, 1 + 4);
1230                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1231                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                          start_y + iDiamondSize, 1 + 8);
1232                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1233                                                                                            start_y - iDiamondSize, 2 + 4);
1234                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1235                                                                                            start_y + iDiamondSize, 2 + 8);
1236                                          break;                                          break;
1237                                  }                                  }
1238                                  if (!(iDirection)) break; //ok, the end. really                                  if (!(iDirection))
1239                                  else                                          break;          //ok, the end. really
1240                                  {       bDirection=iDirection;                                  else {
1241                                          startx=currMV->x; starty=currMV->y;                                          bDirection = iDirection;
1242                                            start_x = currMV->x;
1243                                            start_y = currMV->y;
1244                                  }                                  }
1245                          }                          }
1246                  }                  }
# Line 1044  Line 1250 
1250  }  }
1251    
1252    
1253  int32_t Full8_MainSearch(  int32_t
1254                                          const uint8_t * const pRef,  Full8_MainSearch(const uint8_t * const pRef,
1255                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1256                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1257                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1258                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1259                                          const int x, const int y,                                   const int x,
1260                                          int32_t startx, int32_t starty,                                   const int y,
1261                                          int32_t iMinSAD,                             const int start_x,
1262                               const int start_y,
1263                               int iMinSAD,
1264                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1265                                          const VECTOR * const pmv,                             const int center_x,
1266                                          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1267                                          const int32_t min_dy, const int32_t max_dy,                                   const int32_t min_dx,
1268                                     const int32_t max_dx,
1269                                     const int32_t min_dy,
1270                                     const int32_t max_dy,
1271                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
1272                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
1273                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 1066  Line 1277 
1277          int32_t iSAD;          int32_t iSAD;
1278          int32_t dx,dy;          int32_t dx,dy;
1279          VECTOR backupMV;          VECTOR backupMV;
1280          backupMV.x = startx;  
1281          backupMV.y = starty;          backupMV.x = start_x;
1282            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 1076  Line 1288 
1288          return iMinSAD;          return iMinSAD;
1289  }  }
1290    
1291    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1292    
1293    int32_t
1294  int32_t Halfpel16_Refine(  Halfpel16_Refine(const uint8_t * const pRef,
         const uint8_t * const pRef,  
1295          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1296          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1297          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1298          const uint8_t * const cur,          const uint8_t * const cur,
1299          const int x, const int y,                                   const int x,
1300                                     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 int32_t min_dx, const int32_t max_dx,                             const int center_y,
1305          const int32_t min_dy, const int32_t max_dy,                                   const int32_t min_dx,
1306                                     const int32_t max_dx,
1307                                     const int32_t min_dy,
1308                                     const int32_t max_dy,
1309          const int32_t iFcode,          const int32_t iFcode,
1310          const int32_t iQuant,          const int32_t iQuant,
1311          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1114  Line 1330 
1330  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1331    
1332    
1333  int32_t PMVfastSearch16(  
1334                                          const uint8_t * const pRef,  int32_t
1335    PMVfastSearch16(const uint8_t * const pRef,
1336                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1337                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1338                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1339                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1340                                          const int x, const int y,                                  const int x,
1341                                    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 1154  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    
1385  /* Get maximum range */  /* Get maximum range */
1386          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1387                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1388    
1389  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1390    
1391          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1392          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1393          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1394          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1395          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1396          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1397    
1398          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* 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);
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;
1408                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1409                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1410                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1411                            threshA = 1024;
1412                    if (threshB > 1792)
1413                            threshB = 1792;
1414          }          }
1415    
1416          iFound=0;          iFound=0;
# Line 1201  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          if (!(MotionFlags & PMV_HALFPEL16 ))          currMV->y = start_y;
1427          {       /* This should NOT be necessary! */  
1428            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);
1431          }          }
1432    
1433          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1434                  currMV->x=max_dx;                  currMV->x=max_dx;
1435          }          }
1436          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1437                  currMV->x=min_dx;                  currMV->x=min_dx;
1438          }          }
1439          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1440                  currMV->y=max_dy;                  currMV->y=max_dy;
1441          }          }
1442          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1443                  currMV->y=min_dy;                  currMV->y=min_dy;
1444          }          }
1445    
1446          iMinSAD = sad16( cur,          iMinSAD =
1447                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1448                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1449          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1450            iMinSAD +=
1451          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1452          {                                            (uint8_t) iFcode, iQuant);
1453    
1454            if ((iMinSAD < 256) ||
1455                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1456                     ((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)) {
                         {  
1460                                  iMinSAD += MV16_00_BIAS;                                  iMinSAD += MV16_00_BIAS;
1461                                  CHECK_MV16_ZERO;                // (0,0) saves space for letterboxed pictures                                  CHECK_MV16_ZERO;                // (0,0) saves space for letterboxed pictures
1462                                  iMinSAD -= MV16_00_BIAS;                                  iMinSAD -= MV16_00_BIAS;
# Line 1291  Line 1512 
1512    
1513          if (!MVzero(pmv[1]))          if (!MVzero(pmv[1]))
1514          if (!MVequal(pmv[1],prevMB->mvs[0]))          if (!MVequal(pmv[1],prevMB->mvs[0]))
1515          if (!MVequal(pmv[1],pmv[0]))                          if (!MVequal(pmv[1], pmv[0])) {
1516          {                                  if (!(MotionFlags & PMV_HALFPEL16)) {
1517                  if (!(MotionFlags & PMV_HALFPEL16 ))                                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
1518                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
1519                  }                  }
1520    
1521                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1522          }          }
   
1523  // top neighbour, if allowed  // top neighbour, if allowed
1524          if (!MVzero(pmv[2]))          if (!MVzero(pmv[2]))
1525          if (!MVequal(pmv[2],prevMB->mvs[0]))          if (!MVequal(pmv[2],prevMB->mvs[0]))
1526          if (!MVequal(pmv[2],pmv[0]))          if (!MVequal(pmv[2],pmv[0]))
1527          if (!MVequal(pmv[2],pmv[1]))                                  if (!MVequal(pmv[2], pmv[1])) {
1528          {                                          if (!(MotionFlags & PMV_HALFPEL16)) {
1529                  if (!(MotionFlags & PMV_HALFPEL16 ))                                                  pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
1530                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
1531                  }                  }
1532                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
# Line 1318  Line 1536 
1536                  if (!MVequal(pmv[3],prevMB->mvs[0]))                  if (!MVequal(pmv[3],prevMB->mvs[0]))
1537                  if (!MVequal(pmv[3],pmv[0]))                  if (!MVequal(pmv[3],pmv[0]))
1538                  if (!MVequal(pmv[3],pmv[1]))                  if (!MVequal(pmv[3],pmv[1]))
1539                  if (!MVequal(pmv[3],pmv[2]))                                                                          if (!MVequal(pmv[3], pmv[2])) {
1540                  {                                                                                  if (!(MotionFlags & PMV_HALFPEL16)) {
1541                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                                                          pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
1542                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
1543                          }                          }
1544                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1545                                                                                                                             pmv[3].y);
1546                  }                  }
1547          }          }
1548    
1549          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )          if ((MVzero(*currMV)) &&
1550                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1551                  iMinSAD -= MV16_00_BIAS;                  iMinSAD -= MV16_00_BIAS;
1552    
1553    
# Line 1336  Line 1555 
1555     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1556  */  */
1557    
1558          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1559          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1560                     ((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 1357  Line 1577 
1577    
1578          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
1579                  MainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
1580          else          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
                 if (MotionFlags & PMV_ADVANCEDDIAMOND16)  
1581                          MainSearchPtr = AdvDiamond16_MainSearch;                          MainSearchPtr = AdvDiamond16_MainSearch;
1582                  else                  else
1583                          MainSearchPtr = Diamond16_MainSearch;                          MainSearchPtr = Diamond16_MainSearch;
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 = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1590                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1591                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1592                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1593                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1594                                                      iQuant, iFound);
1595    
1596          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1597                  *currMV = newMV;                  *currMV = newMV;
1598                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1599          }          }
1600    
1601          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1602  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1603    
1604                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1605                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1606                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1607                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1608                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1609                                                                      iDiamondSize, iFcode, iQuant, iFound);
1610    
1611                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1612                          *currMV = newMV;                          *currMV = newMV;
1613                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1614                  }                  }
1615                  }                  }
1616    
1617                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1618                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1619                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1620                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1621                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1622                                                                      iEdgedWidth, iDiamondSize, iFcode,
1623                                                                      iQuant, iFound);
1624    
1625                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1626                          *currMV = newMV;                          *currMV = newMV;
1627                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1628                  }                  }
# Line 1414  Line 1635 
1635    
1636  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1637          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1638                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1639                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1640                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1641                                    pmv, min_dx, max_dx, min_dy, max_dy, 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 1430  Line 1651 
1651    
1652    
1653    
1654  int32_t Diamond8_MainSearch(  int32_t
1655          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1656          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1657          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1658          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1659          const uint8_t * const cur,          const uint8_t * const cur,
1660          const int x, const int y,                                          const int x,
1661          int32_t startx, int32_t starty,                                          const int y,
1662                                            int32_t start_x,
1663                                            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 int32_t min_dx, const int32_t max_dx,                                     const int center_y,
1668          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1669                                            const int32_t max_dx,
1670                                            const int32_t min_dy,
1671                                            const int32_t max_dy,
1672          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1673          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1674          const int32_t iFcode,          const int32_t iFcode,
# Line 1452  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          backupMV.x = startx;  
1685          backupMV.y = starty;          backupMV.x = start_x;
1686            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 1464  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,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1703                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1704                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1705                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1706                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1707                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1708                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1709                                                                                      backupMV.y - iDiamondSize, 3);
1710                            if (iDirectionBackup != 3)
1711                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1712                                                                                      backupMV.y + iDiamondSize, 4);
1713                    }
1714            } else {
1715                    currMV->x = start_x;
1716                    currMV->y = start_y;
1717                  }                  }
1718          else          return iMinSAD;
1719    }
1720    
1721    
1722    
1723    
1724    int32_t
1725    Square8_MainSearch(const uint8_t * const pRef,
1726                                            const uint8_t * const pRefH,
1727                                            const uint8_t * const pRefV,
1728                                            const uint8_t * const pRefHV,
1729                                            const uint8_t * const cur,
1730                                            const int x,
1731                                            const int y,
1732                                            int32_t start_x,
1733                                            int32_t start_y,
1734                                            int32_t iMinSAD,
1735                                            VECTOR * const currMV,
1736                                       const int center_x,
1737                                       const int center_y,
1738                                            const int32_t min_dx,
1739                                            const int32_t max_dx,
1740                                            const int32_t min_dy,
1741                                            const int32_t max_dy,
1742                                            const int32_t iEdgedWidth,
1743                                            const int32_t iDiamondSize,
1744                                            const int32_t iFcode,
1745                                            const int32_t iQuant,
1746                                            int iFound)
1747          {          {
1748                  currMV->x = startx;  /* Do a square search around given starting point, return SAD of best */
1749                  currMV->y = starty;  
1750            int32_t iDirection = 0;
1751            int32_t iSAD;
1752            VECTOR backupMV;
1753    
1754            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    /*   new direction are extra, so 1-4 is normal diamond
1760          537
1761          1*2
1762          648
1763    */
1764    
1765            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1766            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1767            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1768            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1769    
1770            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    
1779    
1780            if (iDirection) {
1781                    while (!iFound) {
1782                            iFound = 1;
1783                            backupMV = *currMV;
1784    
1785                            switch (iDirection) {
1786                            case 1:
1787                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1788                                                                                       backupMV.y, 1);
1789                                    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                            case 3:
1804                                    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                            case 4:
1813                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1814                                                                                     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                            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                            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                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1841                                                                                     backupMV.y - iDiamondSize, 5);
1842                                    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                                    break;
1848    
1849                            case 7:
1850                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1851                                                                                       backupMV.y, 1);
1852                                    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;          return iMinSAD;
1900  }  }
1901    
1902  int32_t Halfpel8_Refine(  
1903          const uint8_t * const pRef,  
1904    
1905    
1906    int32_t
1907    Halfpel8_Refine_c(const uint8_t * const pRef,
1908          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1909          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1910          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1911          const uint8_t * const cur,          const uint8_t * const cur,
1912          const int x, const int y,                                  const int x,
1913                                    const int y,
1914          VECTOR * const currMV,          VECTOR * const currMV,
1915          int32_t iMinSAD,          int32_t iMinSAD,
1916          const VECTOR * const pmv,                             const int center_x,
1917          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1918          const int32_t min_dy, const int32_t max_dy,                                  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,          const int32_t iFcode,
1923          const int32_t iQuant,          const int32_t iQuant,
1924          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1523  Line 1943 
1943    
1944  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1945    
1946  int32_t PMVfastSearch8(  int32_t
1947                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1948                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1949                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1950                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1951                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1952                                          const int x, const int y,                             const int x,
1953                                          const int start_x, const int start_y,                             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,                                          const uint32_t MotionFlags,
1959                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1960                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1563  Line 1987 
1987  //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1988          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1989    
1990          static int32_t threshA,threshB;           int32_t threshA, threshB;
1991          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1992          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1993    
# Line 1576  Line 2000 
2000          startMV.y = start_y;          startMV.y = start_y;
2001    
2002          /* Get maximum range */          /* Get maximum range */
2003          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2004                    x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2005    
2006          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
2007          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2008            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2009            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2010            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2011          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
2012    
2013          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
2014            //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
2015            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 {
2022          else                  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) threshA =  512/4;                  if (threshA < 512 / 4)
2025                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
2026                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
2027                            threshA = 1024 / 4;
2028                    if (threshB > 1792 / 4)
2029                            threshB = 1792 / 4;
2030          }          }
2031    
2032          iFound=0;          iFound=0;
# Line 1616  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 1628  Line 2053 
2053    
2054          *currMV = startMV;          *currMV = startMV;
2055    
2056          iMinSAD = sad8( cur,          iMinSAD =
2057                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2058                          iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2059          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode, iQuant);                                                  iEdgedWidth), iEdgedWidth);
2060            iMinSAD +=
2061                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2062                                             (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 < prevMB->sad8[iSubBlock]) ) )                                                                  && ((int32_t) iMinSAD <
2066          {                                                                          prevMB->sad8[iSubBlock]))) {
2067                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2068                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2069                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1673  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 1684  Line 2112 
2112          if (!MVzero(prevMB->mvs[iSubBlock]))          if (!MVzero(prevMB->mvs[iSubBlock]))
2113          if (!MVequal(prevMB->mvs[iSubBlock],startMV))          if (!MVequal(prevMB->mvs[iSubBlock],startMV))
2114          if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))          if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))
2115          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);                                  CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
2116                                                                            prevMB->mvs[iSubBlock].y);
2117    
2118          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2119          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2120                     ((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)
2124                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
2125          }          }
2126    
   
2127  // left neighbour, if allowed and needed  // left neighbour, if allowed and needed
2128          if (!MVzero(pmv[1]))          if (!MVzero(pmv[1]))
2129          if (!MVequal(pmv[1],startMV))          if (!MVequal(pmv[1],startMV))
2130          if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))          if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))
2131          if (!MVequal(pmv[1],pmv[0]))                                  if (!MVequal(pmv[1], pmv[0])) {
2132          {                                          if (!(MotionFlags & PMV_HALFPEL8)) {
2133                  if (!(MotionFlags & PMV_HALFPEL8 ))                                                  pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2134                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2135                  }                  }
2136                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2137          }          }
   
2138  // top neighbour, if allowed and needed  // top neighbour, if allowed and needed
2139          if (!MVzero(pmv[2]))          if (!MVzero(pmv[2]))
2140          if (!MVequal(pmv[2],startMV))          if (!MVequal(pmv[2],startMV))
2141          if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))          if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))
2142          if (!MVequal(pmv[2],pmv[0]))          if (!MVequal(pmv[2],pmv[0]))
2143          if (!MVequal(pmv[2],pmv[1]))                                          if (!MVequal(pmv[2], pmv[1])) {
2144          {                                                  if (!(MotionFlags & PMV_HALFPEL8)) {
2145                  if (!(MotionFlags & PMV_HALFPEL8 ))                                                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2146                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2147                  }                  }
2148                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
# Line 1727  Line 2153 
2153          if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))          if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))
2154          if (!MVequal(pmv[3],pmv[0]))          if (!MVequal(pmv[3],pmv[0]))
2155          if (!MVequal(pmv[3],pmv[1]))          if (!MVequal(pmv[3],pmv[1]))
2156          if (!MVequal(pmv[3],pmv[2]))                                                                                          if (!MVequal(pmv[3], pmv[2])) {
2157                  {                                                                                                  if (!
2158                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                                                          (MotionFlags &
2159                          {       pmv[3].x = EVEN(pmv[3].x);                                                                                                           PMV_HALFPEL8)) {
2160                                                                                                            pmv[3].x = EVEN(pmv[3].x);
2161                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2162                          }                          }
2163                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
2164                                                                                                                                            pmv[3].y);
2165                  }                  }
2166          }          }
2167    
2168          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )          if ((MVzero(*currMV)) &&
2169                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2170                  iMinSAD -= MV8_00_BIAS;                  iMinSAD -= MV8_00_BIAS;
2171    
2172    
# Line 1745  Line 2174 
2174     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2175  */  */
2176    
2177          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2178          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2179                     ((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 1766  Line 2196 
2196          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2197    
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 = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2200                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2201                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2202                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2203                                                      iQuant, iFound);
2204    
2205          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2206                  *currMV = newMV;                  *currMV = newMV;
2207                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2208          }          }
2209    
2210          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2211  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
2212    
2213                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2214                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2215                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2216                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2217                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2218                                                                      iDiamondSize, iFcode, iQuant, iFound);
2219    
2220                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2221                          *currMV = newMV;                          *currMV = newMV;
2222                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2223                  }                  }
2224                  }                  }
2225    
2226                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2227                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2228                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2229                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2230                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2231                                                                      iQuant, iFound);
2232    
2233                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2234                          *currMV = newMV;                          *currMV = newMV;
2235                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2236                  }                  }
# Line 1814  Line 2243 
2243    
2244  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
2245          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2246                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2247                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2248                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2249                                                   pmv, min_dx, max_dx, min_dy, max_dy, 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  }  }
2258    
2259  int32_t EPZSSearch16(  int32_t
2260                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2261                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2262                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2263                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2264                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2265                                          const int x, const int y,                           const int x,
2266                             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 1864  Line 2298 
2298          int32_t psad[8];          int32_t psad[8];
2299    
2300          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2301    
2302  //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
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    
2310          MainSearch16FuncPtr MainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2311    
2312          if (oldMBs == NULL)          if (oldMBs == NULL) {
2313          {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2314  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2315          }          }
2316          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2317    
2318  /* Get maximum range */  /* Get maximum range */
2319          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2320                          x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
2321    
2322          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
2323          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2324            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2325            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2326            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2327          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2328            /* 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 1902  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          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2343          {  
2344            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);
2347          }          }
# Line 1920  Line 2357 
2357    
2358  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2359    
2360          iMinSAD = sad16( cur,          iMinSAD =
2361                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2362                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2363          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2364            iMinSAD +=
2365                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2366                                              (uint8_t) iFcode, iQuant);
2367    
2368  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2369          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD < 256) ||
2370                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2371                     ((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 1942  Line 2383 
2383  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2384  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
2385    
2386          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2387                  thresh2 =  512;                  thresh2 =  512;
2388          }          } else {
         else  
         {  
2389  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
2390    
2391                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1959  Line 2397 
2397    
2398    
2399  // left neighbour, if allowed  // left neighbour, if allowed
2400          if (x != 0)          if (x != 0) {
2401          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2402                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2403                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2404                  }                  }
2405                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2406          }          }
   
2407  // top neighbour, if allowed  // top neighbour, if allowed
2408          if (y != 0)          if (y != 0) {
2409          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2410                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2411                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2412                  }                  }
2413                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
2414    
2415  // top right neighbour, if allowed  // top right neighbour, if allowed
2416                  if ((uint32_t)x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
2417                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2418                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2419                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2420                          }                          }
2421                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1993  Line 2427 
2427  */  */
2428    
2429          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2430                  || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2431                  {                          ((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 2015  Line 2449 
2449    
2450  // top neighbour  // top neighbour
2451          if (y != 0)          if (y != 0)
2452                  CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2453                                                             (prevMB - iWcount)->mvs[0].y);
2454    
2455  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2456    
# Line 2024  Line 2459 
2459    
2460  // bottom neighbour, dito  // bottom neighbour, dito
2461          if ((uint32_t)y != iHcount-1)          if ((uint32_t)y != iHcount-1)
2462                  CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2463                                                             (prevMB + iWcount)->mvs[0].y);
2464    
2465  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2466          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2) {
                 {  
2467                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2468                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2469                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 2039  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_USESQUARES16)
2478                    MainSearchPtr = Square16_MainSearch;
2479            else
2480             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2481                    MainSearchPtr = AdvDiamond16_MainSearch;
2482            else
2483                    MainSearchPtr = Diamond16_MainSearch;
2484    
2485  /* 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 */
2486    
2487          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2488                          x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2489                          currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2490                          2, iFcode, iQuant, 0);                                                    min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2491    
2492          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2493                  *currMV = newMV;                  *currMV = newMV;
2494                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2495          }          }
2496    
2497    
2498          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
2499  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2500    
2501                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2502                  {                          iSAD =
2503                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2504                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2505                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2506                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2507                  }                  }
2508    
2509                  if (iSAD < iMinSAD)                  if (iSAD < iMinSAD) {
                 {  
2510                          *currMV = newMV;                          *currMV = newMV;
2511                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2512                  }                  }
2513    
2514                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2515                  {                          iSAD =
2516                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2517                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2518                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
                         pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);  
2519    
2520                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2521                                  *currMV = newMV;                                  *currMV = newMV;
2522                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2523                          }                          }
# Line 2090  Line 2528 
2528    
2529  EPZS16_Terminate_with_Refine:  EPZS16_Terminate_with_Refine:
2530          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
2531                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2532                                  x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2533                                  currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2534                                  pmv, min_dx, max_dx, min_dy, max_dy, 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    
2545    
2546  int32_t EPZSSearch8(  int32_t
2547                                          const uint8_t * const pRef,  EPZSSearch8(const uint8_t * const pRef,
2548                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2549                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2550                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2551                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2552                                          const int x, const int y,                          const int x,
2553                                          const int start_x, const int start_y,                          const int y,
2554                            const int start_x,
2555                            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 2155  Line 2597 
2597          MainSearch8FuncPtr MainSearchPtr;          MainSearch8FuncPtr MainSearchPtr;
2598    
2599  /* Get maximum range */  /* Get maximum range */
2600          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2601                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2602    
2603  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2604    
2605          if (!(MotionFlags & PMV_HALFPEL8 ))          if (!(MotionFlags & PMV_HALFPEL8)) {
2606          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2607            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2608            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2609            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2610          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2611            /* 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 2180  Line 2623 
2623  // Prepare for main loop  // Prepare for main loop
2624    
2625    
2626          if (!(MotionFlags & PMV_HALFPEL8))          if (!(MotionFlags & PMV_HALFPEL8)) {
         {  
2627                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2628                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2629          }          }
# Line 2198  Line 2640 
2640  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2641    
2642    
2643          iMinSAD = sad8( cur,          iMinSAD =
2644                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2645                  iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2646          iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                  iEdgedWidth), iEdgedWidth);
2647            iMinSAD +=
2648                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2649                                             (uint8_t) iFcode, iQuant);
2650    
2651    
2652  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2653          if (iMinSAD < 256/4 )          if (iMinSAD < 256 / 4) {
                 {  
2654                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2655                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2656                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 2223  Line 2667 
2667          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
2668    
2669  // left neighbour, if allowed  // left neighbour, if allowed
2670          if (psad[1] != MV_MAX_ERROR)          if (psad[1] != MV_MAX_ERROR) {
2671          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2672                  if (!(MotionFlags & PMV_HALFPEL8 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2673                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2674                  }                  }
2675                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2676          }          }
   
2677  // top neighbour, if allowed  // top neighbour, if allowed
2678          if (psad[2] != MV_MAX_ERROR)          if (psad[2] != MV_MAX_ERROR) {
2679          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2680                  if (!(MotionFlags & PMV_HALFPEL8 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2681                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2682                  }                  }
2683                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2684    
2685  // top right neighbour, if allowed  // top right neighbour, if allowed
2686                  if (psad[3] != MV_MAX_ERROR)                  if (psad[3] != MV_MAX_ERROR) {
2687                  {                          if (!(MotionFlags & PMV_HALFPEL8)) {
2688                          if (!(MotionFlags & PMV_HALFPEL8 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2689                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2690                          }                          }
2691                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 2263  Line 2703 
2703     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2704  */  */
2705    
2706          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
                 {  
2707                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2708                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2709                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 2280  Line 2719 
2719    
2720  /* default: use best prediction as starting point for one call of EPZS_MainSearch */  /* default: use best prediction as starting point for one call of EPZS_MainSearch */
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
 */  
   
 //      if (MotionFlags & PMV_USESQUARES8)  
 //              MainSearchPtr = Square8_MainSearch;  
 //      else  
2727    
2728          if (MotionFlags & PMV_ADVANCEDDIAMOND8)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2729                  MainSearchPtr = AdvDiamond8_MainSearch;                  MainSearchPtr = AdvDiamond8_MainSearch;
2730          else          else
2731                  MainSearchPtr = Diamond8_MainSearch;                  MainSearchPtr = Diamond8_MainSearch;
2732    
2733          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2734                  x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2735                  currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2736                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2737                  iDiamondSize, iFcode, iQuant, 0);                                                    iQuant, 0);
2738    
2739    
2740          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2741                  *currMV = newMV;                  *currMV = newMV;
2742                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2743          }          }
2744    
2745          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2746  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2747    
2748                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2749                  {                          iSAD =
2750                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2751                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2752                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2753                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2754    
2755                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2756                                  *currMV = newMV;                                  *currMV = newMV;
2757                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2758                          }                          }
2759                  }                  }
2760    
2761                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2762                  {                          iSAD =
2763                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2764                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2765                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2766                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, 0);
2767    
2768                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2769                                  *currMV = newMV;                                  *currMV = newMV;
2770                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2771                          }                          }
# Line 2346  Line 2776 
2776    
2777  EPZS8_Terminate_with_Refine:  EPZS8_Terminate_with_Refine:
2778          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2779                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2780                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2781                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2782                                  pmv, min_dx, max_dx, min_dy, max_dy, 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
3092  void MotionEstimationBVOP(  MotionEstimationBVOP(MBParam * const pParam,
                         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 2385  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;
         int32_t f_sad16;  
         int32_t b_sad16;  
         int32_t i_sad16;  
         int32_t d_sad16;  
         int32_t best_sad;  
3115    
3116            int i, j, k;
3117    
3118            static const VECTOR zeroMV={0,0};
3119    
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                  for (i = 0; i < mb_width; i++)                  f_predMV = zeroMV;      /* prediction is reset at left boundary */
3148                  {                  b_predMV = zeroMV;
3149    
3150                    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                          if (b_mb->mode == MODE_INTER                          mb->deltamv=zeroMV;
3156                                  && b_mb->cbp == 0  
3157                                  && b_mb->mvs[0].x == 0  /* special case, if collocated block is SKIPed: encoding is forward (0,0), cpb=0 without further ado */
3158                                  && b_mb->mvs[0].y == 0)  
3159                          {                          if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
3160                                    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                          }                          }
3165    
3166                            if (b_mb->mode == MODE_INTER4V)
3167                            {
3168                                    d_sad16 = 0;
3169                            /* same method of scaling as in decoder.c, so we copy from there */
3170                        for (k = 0; k < 4; k++) {
3171    
3172                                            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 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                          f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3220                                                  &frame->image,                                                  &frame->image, i, j,
3221                                                  i, j,                                                  mb->mvs[0].x, mb->mvs[0].y,                     /* start point f_directMV */
3222                                                  frame->motion_flags,  frame->quant, frame->fcode,                                                  f_predMV.x, f_predMV.y,                         /* center is f-prediction */
3223                                                  pParam,                                                  frame->motion_flags,
3224                                                  f_mbs, f_mbs /* todo */,                                                  frame->quant, frame->fcode, pParam,
3225                                                  &mb->mvs[0], &pmv_dontcare);    // ignore pmv                                                  f_mbs, f_mbs,
3226                                                    &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,                                                  &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,
3236                                                    b_mbs, b_mbs,
3237                                                    &mb->b_mvs[0], &pmv_dontcare);
3238    
3239                            i_sad16 =
3240                                    sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3241                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3242                                                                    i, j, 16, &mb->mvs[0], edged_width),
3243                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3244                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
3245                                                      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                        i_sad16 += calc_delta_16(mb->b_mvs[0].x-b_predMV.x, mb->b_mvs[0].y-b_predMV.y,
3249                                                                    frame->bcode, frame->quant);
3250    
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,                                                  i, j,
3266                                                  frame->motion_flags,  frame->quant, frame->bcode,                                                  mb->mvs[0].x, mb->mvs[0].y,
3267                                                  pParam,                                                  mb->b_mvs[0].x, mb->b_mvs[0].y,
3268                                                  b_mbs, b_mbs, /* todo */                                                  i_sad16,
3269                                                  &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv                                                  &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                          // interpolate search (simple, but effective)                          i_sad16 = Diamond16_InterpolMainSearch(
3277                          i_sad16 = sad16bi_c(                                                  f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3278                                          frame->image.y + i*16 + j*16*edged_width,                                          frame->image.y + i*16 + j*16*edged_width,
3279                                          get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                                  b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3280                                                  i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),                                                  i, j,
3281                                          get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                                                  f_interpolMV.x, f_interpolMV.y,
3282                                                  i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),                                                  b_interpolMV.x, b_interpolMV.y,
3283                                          edged_width);                                                  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                          // TODO: direct search                          get_range(&min_dx, &max_dx, &min_dy, &max_dy, i, j, 16, iWidth, iHeight, 19);
                         // predictor + range of [-32,32]  
                         d_sad16 = 65535;  
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                          if (f_sad16 < b_sad16)                          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) {
3334                                  best_sad = f_sad16;                                  best_sad = f_sad16;
3335                                  mb->mode = MODE_FORWARD;                                  mb->mode = MODE_FORWARD;
3336                          }                          } else {
                         else  
                         {  
3337                                  best_sad = b_sad16;                                  best_sad = b_sad16;
3338                                  mb->mode = MODE_BACKWARD;                                  mb->mode = MODE_BACKWARD;
3339                          }                          }
3340    
3341                          if (i_sad16 < best_sad)                          if (i_sad16 < best_sad) {
                         {  
3342                                  best_sad = i_sad16;                                  best_sad = i_sad16;
3343                                  mb->mode = MODE_INTERPOLATE;                                  mb->mode = MODE_INTERPOLATE;
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.181  
changed lines
  Added in v.430

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