[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 136, Thu Apr 25 06:55:00 2002 UTC revision 524, Sun Sep 22 20:34:05 2002 UTC
# Line 1  Line 1 
1  /**************************************************************************  /*****************************************************************************
2   *   *
3   *  Modifications:   *  XVID MPEG-4 VIDEO CODEC
4     *  - Motion Estimation module -
5   *   *
6   *      25.04.2002 partial prevMB conversion   *  Copyright(C) 2002 Christoph Lampert <gruel@web.de>
7   *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>   *  Copyright(C) 2002 Michael Militzer <michael@xvid.org>
8   *  14.04.2002 added MotionEstimationBVOP()   *  Copyright(C) 2002 Edouard Gomez <ed.gomez@wanadoo.fr>
  *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between  
  *             EPZS and EPZS^2  
  *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop  
  *             PMVFast_Refine to support multiple searches with different start points  
  *  07.01.2002 uv-block-based interpolation  
  *  06.01.2002 INTER/INTRA-decision is now done before any SEARCH8 (speedup)  
  *             changed INTER_BIAS to 150 (as suggested by suxen_drol)  
  *             removed halfpel refinement step in PMVfastSearch8 + quality=5  
  *             added new quality mode = 6 which performs halfpel refinement  
  *             filesize difference between quality 5 and 6 is smaller than 1%  
  *             (Isibaar)  
  *  31.12.2001 PMVfastSearch16 and PMVfastSearch8 (gruel)  
  *  30.12.2001 get_range/MotionSearchX simplified; blue/green bug fix  
  *  22.12.2001 commented best_point==99 check  
  *  19.12.2001 modified get_range (purple bug fix)  
  *  15.12.2001 moved pmv displacement from mbprediction  
  *  02.12.2001 motion estimation/compensation split (Isibaar)  
  *  16.11.2001 rewrote/tweaked search algorithms; pross@cs.rmit.edu.au  
  *  10.11.2001 support for sad16/sad8 functions  
  *  28.08.2001 reactivated MODE_INTER4V for EXT_MODE  
  *  24.08.2001 removed MODE_INTER4V_Q, disabled MODE_INTER4V for EXT_MODE  
  *  22.08.2001 added MODE_INTER4V_Q  
  *  20.08.2001 added pragma to get rid of internal compiler error with VC6  
  *             idea by Cyril. Thanks.  
9   *   *
10   *  Michael Militzer <isibaar@videocoding.de>   *  This program is an implementation of a part of one or more MPEG-4
11     *  Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
12     *  to use this software module in hardware or software products are
13     *  advised that its use may infringe existing patents or copyrights, and
14     *  any such use would be at such party's own risk.  The original
15     *  developer of this software module and his/her company, and subsequent
16     *  editors and their companies, will have no liability for use of this
17     *  software or modifications or derivatives thereof.
18   *   *
19   **************************************************************************/   *  This program is free software; you can redistribute it and/or modify
20     *  it under the terms of the GNU General Public License as published by
21     *  the Free Software Foundation; either version 2 of the License, or
22     *  (at your option) any later version.
23     *
24     *  This program is distributed in the hope that it will be useful,
25     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
26     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27     *  GNU General Public License for more details.
28     *
29     *  You should have received a copy of the GNU General Public License
30     *  along with this program; if not, write to the Free Software
31     *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
32     *
33     *************************************************************************/
34    
35  #include <assert.h>  #include <assert.h>
36  #include <stdio.h>  #include <stdio.h>
# Line 46  Line 44 
44  #include "motion.h"  #include "motion.h"
45  #include "sad.h"  #include "sad.h"
46    
 // very large value  
 #define MV_MAX_ERROR    (4096 * 256)  
   
 // stop search if sdelta < THRESHOLD  
 #define MV16_THRESHOLD  192  
 #define MV8_THRESHOLD   56  
   
 /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  
 /* nb  = vop pixels * 2^(bpp-8) */  
 #define MV16_00_BIAS    (128+1)  
   
 /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */  
 #define 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)  
   
   
 int32_t PMVfastSearch16(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
 int32_t EPZSSearch16(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
47    
48    
49  int32_t PMVfastSearch8(  static int32_t lambda_vec16[32] =       /* rounded values for lambda param for weight of motion bits as in modified H.26L */
50                                          const uint8_t * const pRef,  { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),
51                                          const uint8_t * const pRefH,                  (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),
52                                          const uint8_t * const pRefV,          (int) (1.89187 + 0.5), (int) (2.11542 + 0.5), (int) (2.35878 + 0.5),
53                                          const uint8_t * const pRefHV,                  (int) (2.62429 + 0.5), (int) (2.91455 + 0.5),
54                                          const IMAGE * const pCur,          (int) (3.23253 + 0.5), (int) (3.58158 + 0.5), (int) (3.96555 + 0.5),
55                                          const int x, const int y,                  (int) (4.38887 + 0.5), (int) (4.85673 + 0.5),
56                                          const int start_x, const int start_y,          (int) (5.37519 + 0.5), (int) (5.95144 + 0.5), (int) (6.59408 + 0.5),
57                                          const uint32_t MotionFlags,                  (int) (7.31349 + 0.5), (int) (8.12242 + 0.5),
58                                          const uint32_t iQuant,          (int) (9.03669 + 0.5), (int) (10.0763 + 0.5), (int) (11.2669 + 0.5),
59                                          const uint32_t iFcode,                  (int) (12.6426 + 0.5), (int) (14.2493 + 0.5),
60                                          const MBParam * const pParam,          (int) (16.1512 + 0.5), (int) (18.442 + 0.5), (int) (21.2656 + 0.5),
61                                          const MACROBLOCK * const pMBs,                  (int) (24.8580 + 0.5), (int) (29.6436 + 0.5),
62                                          const MACROBLOCK * const prevMBs,          (int) (36.4949 + 0.5)
63                                          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);  
64    
65  typedef MainSearch16Func* MainSearch16FuncPtr;  static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now */
66    
67    
 typedef int32_t (MainSearch8Func)(  
         const uint8_t * const pRef,  
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const uint8_t * const cur,  
         const int x, const int y,  
         int32_t startx, int32_t starty,  
         int32_t iMinSAD,  
         VECTOR * const currMV,  
         const VECTOR * const pmv,  
         const int32_t min_dx, const int32_t max_dx,  
         const int32_t min_dy, const int32_t max_dy,  
         const int32_t iEdgedWidth,  
         const int32_t iDiamondSize,  
         const int32_t iFcode,  
         const int32_t iQuant,  
         int iFound);  
   
 typedef MainSearch8Func* MainSearch8FuncPtr;  
68    
69  // mv.length table  // mv.length table
70  static const uint32_t mvtab[33] = {  static const uint32_t mvtab[33] = {
# Line 192  Line 75 
75  };  };
76    
77    
78  static __inline uint32_t mv_bits(int32_t component, const uint32_t iFcode)  static __inline uint32_t
79    mv_bits(int32_t component,
80                    const uint32_t iFcode)
81  {  {
82      if (component == 0)      if (component == 0)
83                  return 1;                  return 1;
# Line 200  Line 85 
85      if (component < 0)      if (component < 0)
86                  component = -component;                  component = -component;
87    
88      if (iFcode == 1)          if (iFcode == 1) {
     {  
89                  if (component > 32)                  if (component > 32)
90                      component = 32;                      component = 32;
91    
# Line 218  Line 102 
102  }  }
103    
104    
105  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode)  static __inline uint32_t
106    calc_delta_16(const int32_t dx,
107                              const int32_t dy,
108                              const uint32_t iFcode,
109                              const uint32_t iQuant)
110  {  {
111          return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));          return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) +
112                                                                                                              mv_bits(dy, iFcode));
113  }  }
114    
115  static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)  static __inline uint32_t
116    calc_delta_8(const int32_t dx,
117                             const int32_t dy,
118                             const uint32_t iFcode,
119                             const uint32_t iQuant)
120  {  {
121      return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));          return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) +
122                                                                                                       mv_bits(dy, iFcode));
123  }  }
124    
125    bool
126    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,  
127          FRAMEINFO * const current,          FRAMEINFO * const current,
128          FRAMEINFO * const reference,          FRAMEINFO * const reference,
129          const IMAGE * const pRefH,          const IMAGE * const pRefH,
130          const IMAGE * const pRefV,          const IMAGE * const pRefV,
131          const IMAGE * const pRefHV,          const IMAGE * const pRefHV,
132          const uint32_t iLimit)          const uint32_t iLimit)
   
133  {  {
134          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
135          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
136          MACROBLOCK * pMBs = current->mbs;          MACROBLOCK *const pMBs = current->mbs;
137          IMAGE * pCurrent = &current->image;          MACROBLOCK *const prevMBs = reference->mbs;
138            const IMAGE *const pCurrent = &current->image;
139          MACROBLOCK * prevMBs = reference->mbs;  // previous frame          const IMAGE *const pRef = &reference->image;
140          IMAGE * pRef = &reference->image;  
141            static const VECTOR zeroMV = { 0, 0 };
142            VECTOR predMV;
143          uint32_t i, j, iIntra = 0;  
144            uint32_t x, y;
145          VECTOR mv16;          uint32_t iIntra = 0;
146          VECTOR pmv16;          VECTOR pmv;
   
         int32_t sad8 = 0;  
         int32_t sad16;  
         int32_t deviation;  
147    
148          if (sadInit)          if (sadInit)
149                  (*sadInit)();                  (*sadInit)();
150    
151            for (y = 0; y < iHcount; y++)   {
152                    for (x = 0; x < iWcount; x ++)  {
153    
154          /* eventhough we have a seperate prevMBs,                          MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
            pmvfast/epsz does something "funny" with the previous frames data */  
   
         for (i = 0; i < iHcount; i++)  
                 for (j = 0; j < iWcount; j++)  
                 {  
                         pMBs[j + i * iWcount].mvs[0] = prevMBs[j + i * iWcount].mvs[0];  
                         pMBs[j + i * iWcount].mvs[1] = prevMBs[j + i * iWcount].mvs[1];  
                         pMBs[j + i * iWcount].mvs[2] = prevMBs[j + i * iWcount].mvs[2];  
                         pMBs[j + i * iWcount].mvs[3] = prevMBs[j + i * iWcount].mvs[3];  
                 }  
   
         /*dprintf("*** BEFORE ***");  
         for (i = 0; i < iHcount; i++)  
                 for (j = 0; j < iWcount; j++)  
                 {  
                         dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,  
                                 pMBs[j + i * iWcount].mode,  
                                 pMBs[j + i * iWcount].dquant,  
                                 pMBs[j + i * iWcount].mvs[0],  
                                 pMBs[j + i * iWcount].mvs[1],  
                                 pMBs[j + i * iWcount].mvs[2],  
                                 pMBs[j + i * iWcount].mvs[3],  
                                 prevMBs[j + i * iWcount].sad8[0],  
                                 prevMBs[j + i * iWcount].sad8[1],  
                                 prevMBs[j + i * iWcount].sad8[2],  
                                 prevMBs[j + i * iWcount].sad8[3],  
                                 prevMBs[j + i * iWcount].sad16);  
                 }  
         */  
   
         // note: i==horizontal, j==vertical  
         for (i = 0; i < iHcount; i++)  
                 for (j = 0; j < iWcount; j++)  
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
                         MACROBLOCK *prevMB = &prevMBs[j + i * iWcount];  
155    
156                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
                                          j, i, current->motion_flags, current->quant, current->fcode,  
                                          pParam, pMBs, prevMBs, &mv16, &pmv16);  
                         pMB->sad16=sad16;  
157    
158                            pMB->sad16 =
159                                    SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
160                                                     x, y, predMV.x, predMV.y, predMV.x, predMV.y,
161                                                     current->motion_flags, current->quant,
162                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
163                                                     &pMB->pmvs[0]);
164    
165                          /* decide: MODE_INTER or MODE_INTRA                          if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
166                             if (dev_intra < sad_inter - 2 * nb) use_intra                                  int32_t deviation;
                         */  
167    
168                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                                  deviation =
169                                            dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
170                                                      pParam->edged_width);
171    
172                          if (deviation < (sad16 - INTER_BIAS))                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
                         {  
173                                  pMB->mode = MODE_INTRA;                                  pMB->mode = MODE_INTRA;
174                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
175                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                                  pMB->mvs[3] = zeroMV;
176                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
177                                  pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
178    
179                                  iIntra++;                                  iIntra++;
180                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 340  Line 182 
182    
183                                  continue;                                  continue;
184                          }                          }
185                            }
186    
187                            pmv = pMB->pmvs[0];
188                          if (current->global_flags & XVID_INTER4V)                          if (current->global_flags & XVID_INTER4V)
189                          {                                  if ((!(current->global_flags & XVID_LUMIMASKING) ||
190                                  pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                           pMB->dquant == NO_CHANGE)) {
191                                                         2 * j, 2 * i, mv16.x, mv16.y,                                          int32_t sad8 = IMV16X16 * current->quant;
192                                                             current->motion_flags, current->quant, current->fcode,  
193                                                         pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);                                          if (sad8 < pMB->sad16) {
194                                                    sad8 += pMB->sad8[0] =
195                                  pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
196                                                         2 * j + 1, 2 * i, mv16.x, mv16.y,                                                                          pCurrent, 2 * x, 2 * y,
197                                                             current->motion_flags, current->quant, current->fcode,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
198                                                         pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);                                                                          current->motion_flags,
199                                                                            current->quant, current->fcode, pParam,
200                                  pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                                          pMBs, prevMBs, &pMB->mvs[0],
201                                                         2 * j, 2 * i + 1, mv16.x, mv16.y,                                                                          &pMB->pmvs[0]);
202                                                             current->motion_flags, current->quant, current->fcode,                                          }
203                                                         pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);                                          if (sad8 < pMB->sad16) {
204    
205                                  pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                  predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
206                                                         2 * j + 1, 2 * i + 1, mv16.x, mv16.y,                                                  sad8 += pMB->sad8[1] =
207                                                             current->motion_flags, current->quant, current->fcode,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
208                                                         pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);                                                                          pCurrent, 2 * x + 1, 2 * y,
209                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
210                                  sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];                                                                          current->motion_flags,
211                                                                            current->quant, current->fcode, pParam,
212                                                                            pMBs, prevMBs, &pMB->mvs[1],
213                                                                            &pMB->pmvs[1]);
214                                            }
215                                            if (sad8 < pMB->sad16) {
216                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
217                                                    sad8 += pMB->sad8[2] =
218                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
219                                                                            pCurrent, 2 * x, 2 * y + 1,
220                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
221                                                                            current->motion_flags,
222                                                                            current->quant, current->fcode, pParam,
223                                                                            pMBs, prevMBs, &pMB->mvs[2],
224                                                                            &pMB->pmvs[2]);
225                                            }
226                                            if (sad8 < pMB->sad16) {
227                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
228                                                    sad8 += pMB->sad8[3] =
229                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
230                                                                            pCurrent, 2 * x + 1, 2 * y + 1,
231                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
232                                                                            current->motion_flags,
233                                                                            current->quant, current->fcode, pParam,
234                                                                            pMBs, prevMBs,
235                                                                            &pMB->mvs[3],
236                                                                            &pMB->pmvs[3]);
237                          }                          }
238    
   
239                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
240                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
241                          */                          */
242    
243                          if (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE)                                          if (sad8 < pMB->sad16) {
                         {  
                                 if (((current->global_flags & XVID_INTER4V)==0) ||  
                                     (sad16 < (sad8 + (int32_t)(IMV16X16 * current->quant))))  
                                 {  
   
                                         sad8 = sad16;  
                                         pMB->mode = MODE_INTER;  
                                         pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;  
                                         pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;  
                                         pMB->pmvs[0].x = pmv16.x;  
                                         pMB->pmvs[0].y = pmv16.y;  
                                 }  
                                 else  
244                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
245                                                    pMB->sad8[0] *= 4;
246                                                    pMB->sad8[1] *= 4;
247                                                    pMB->sad8[2] *= 4;
248                                                    pMB->sad8[3] *= 4;
249                                                    continue;
250                          }                          }
251                          else  
                         {  
                                 sad8 = sad16;  
                                 pMB->mode = MODE_INTER;  
                                 pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;  
                                 pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;  
                                 pMB->pmvs[0].x = pmv16.x;  
                                 pMB->pmvs[0].y = pmv16.y;  
                         }  
252                  }                  }
253    
254  /*      dprintf("*** AFTER ***", pMBs[0].b_mvs[0].x);                          pMB->mode = MODE_INTER;
255          for (i = 0; i < iHcount; i++)                          pMB->pmvs[0] = pmv;     /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
256                  for (j = 0; j < iWcount; j++)                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
257                  {                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
258                          dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,                                  pMB->sad16;
259                                  pMBs[j + i * iWcount].mode,                          }
                                 pMBs[j + i * iWcount].dquant,  
                                 pMBs[j + i * iWcount].mvs[0],  
                                 pMBs[j + i * iWcount].mvs[1],  
                                 pMBs[j + i * iWcount].mvs[2],  
                                 pMBs[j + i * iWcount].mvs[3],  
                                 pMBs[j + i * iWcount].sad8[0],  
                                 pMBs[j + i * iWcount].sad8[1],  
                                 pMBs[j + i * iWcount].sad8[2],  
                                 pMBs[j + i * iWcount].sad8[3],  
                                 pMBs[j + i * iWcount].sad16);  
260                  }                  }
         */  
261    
262          return 0;          return 0;
263  }  }
264    
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
   
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
265    
266  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
267    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
268      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
269    { \    { \
270      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \
271      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
     if (iSAD <= iQuant * 96)    \  
         iSAD -= MV16_00_BIAS; \  
272      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
273      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
274  }  }
275    
276  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
277      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
278      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
279      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
280      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
281  }  }
# Line 449  Line 285 
285      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
286    { \    { \
287      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
288      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
289      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
290      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
291  }  }
# Line 459  Line 295 
295      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
296    { \    { \
297      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
298      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
299      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
300      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
301  }  }
# Line 469  Line 305 
305      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
306    { \    { \
307      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
308      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
309      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
310      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
311  }  }
# Line 477  Line 313 
313    
314  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
315    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \
316    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\    iSAD += calc_delta_8(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
317    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
318    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
319  }  }
# Line 485  Line 321 
321  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
322    { \    { \
323      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
324      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
325      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
326      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
327  }  }
# Line 495  Line 331 
331      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
332    { \    { \
333      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
334      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
335      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
336      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
337  }  }
# Line 505  Line 341 
341      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
342    { \    { \
343      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
344      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
345      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
346      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
347  }  }
# Line 515  Line 351 
351      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
352    { \    { \
353      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
354      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
355      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
356      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
357  }  }
358    
359    #if 0
360  /* too slow and not fully functional at the moment */  /* too slow and not fully functional at the moment */
 /*  
361  int32_t ZeroSearch16(  int32_t ZeroSearch16(
362                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
363                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
# Line 541  Line 377 
377          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
378          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
379          int32_t iSAD;          int32_t iSAD;
380          int32_t pred_x,pred_y;          VECTOR pred;
381    
382    
383          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
384    
385          iSAD = sad16( cur,          iSAD = sad16( cur,
386                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
# Line 553  Line 390 
390    
391          currMV->x = 0;          currMV->x = 0;
392          currMV->y = 0;          currMV->y = 0;
393          currPMV->x = -pred_x;          currPMV->x = -pred.x;
394          currPMV->y = -pred_y;          currPMV->y = -pred.y;
395    
396          return iSAD;          return iSAD;
397    
398  }  }
399  */  #endif /* 0 */
400    
401  int32_t Diamond16_MainSearch(  int32_t
402          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
403          const uint8_t * const pRefH,          const uint8_t * const pRefH,
404          const uint8_t * const pRefV,          const uint8_t * const pRefV,
405          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
406          const uint8_t * const cur,          const uint8_t * const cur,
407          const int x, const int y,                                           const int x,
408          int32_t startx, int32_t starty,                                           const int y,
409          int32_t iMinSAD,                                           const int start_x,
410                                             const int start_y,
411                                             int iMinSAD,
412          VECTOR * const currMV,          VECTOR * const currMV,
413          const VECTOR * const pmv,                                           const int center_x,
414          const int32_t min_dx, const int32_t max_dx,                                           const int center_y,
415          const int32_t min_dy, const int32_t max_dy,                                           const int32_t min_dx,
416                                             const int32_t max_dx,
417                                             const int32_t min_dy,
418                                             const int32_t max_dy,
419          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
420          const int32_t iDiamondSize,          const int32_t iDiamondSize,
421          const int32_t iFcode,          const int32_t iFcode,
# Line 583  Line 425 
425  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
426    
427          int32_t iDirection=0;          int32_t iDirection=0;
428            int32_t iDirectionBackup;
429          int32_t iSAD;          int32_t iSAD;
430          VECTOR backupMV;          VECTOR backupMV;
431          backupMV.x = startx;  
432          backupMV.y = starty;          backupMV.x = start_x;
433            backupMV.y = start_y;
434    
435  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
436    
# Line 595  Line 439 
439          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
440          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
441    
442          if (iDirection)          if (iDirection) {
443                  while (!iFound)                  while (!iFound) {
                 {  
444                          iFound = 1;                          iFound = 1;
445                          backupMV=*currMV;                          backupMV=*currMV;
446                            iDirectionBackup = iDirection;
447    
448                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
449                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
450                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
451                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
452                          if ( iDirection != 4)                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
453                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                     backupMV.y, 2);
454                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
455                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
456                                                                                       backupMV.y - iDiamondSize, 3);
457                            if (iDirectionBackup != 3)
458                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
459                                                                                       backupMV.y + iDiamondSize, 4);
460                  }                  }
461          else          } else {
462          {                  currMV->x = start_x;
463                  currMV->x = startx;                  currMV->y = start_y;
                 currMV->y = starty;  
464          }          }
465          return iMinSAD;          return iMinSAD;
466  }  }
467    
468  int32_t Square16_MainSearch(  int32_t
469                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
470                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
471                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
472                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
473                                          const uint8_t * const cur,                                          const uint8_t * const cur,
474                                          const int x, const int y,                                          const int x,
475                                          int32_t startx, int32_t starty,                                          const int y,
476                                          int32_t iMinSAD,                                          const int start_x,
477                                            const int start_y,
478                                            int iMinSAD,
479                                          VECTOR * const currMV,                                          VECTOR * const currMV,
480                                          const VECTOR * const pmv,                                          const int center_x,
481                                          const int32_t min_dx, const int32_t max_dx,                                          const int center_y,
482                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
483                                            const int32_t max_dx,
484                                            const int32_t min_dy,
485                                            const int32_t max_dy,
486                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
487                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
488                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 642  Line 494 
494          int32_t iDirection=0;          int32_t iDirection=0;
495          int32_t iSAD;          int32_t iSAD;
496          VECTOR backupMV;          VECTOR backupMV;
497          backupMV.x = startx;  
498          backupMV.y = starty;          backupMV.x = start_x;
499            backupMV.y = start_y;
500    
501  /* It's one search with full square pattern, and new parts for all following diamonds */  /* It's one search with full square pattern, and new parts for all following diamonds */
502    
# Line 658  Line 511 
511          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
512          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
513    
514          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
515          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
516          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
517          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
518            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
519                                                             backupMV.y - iDiamondSize, 7);
520            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
521                                                             backupMV.y + iDiamondSize, 8);
522    
523    
524          if (iDirection)          if (iDirection) {
525                  while (!iFound)                  while (!iFound) {
                 {  
526                          iFound = 1;                          iFound = 1;
527                          backupMV=*currMV;                          backupMV=*currMV;
528    
529                          switch (iDirection)                          switch (iDirection) {
                         {  
530                                  case 1:                                  case 1:
531                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
532                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
533                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
534                                                                                     backupMV.y - iDiamondSize, 5);
535                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
536                                                                                     backupMV.y - iDiamondSize, 7);
537                                          break;                                          break;
538                                  case 2:                                  case 2:
539                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
540                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
541                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
542                                                                                     backupMV.y + iDiamondSize, 6);
543                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
544                                                                                     backupMV.y + iDiamondSize, 8);
545                                          break;                                          break;
546    
547                                  case 3:                                  case 3:
548                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
549                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
550                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
551                                                                                     backupMV.y - iDiamondSize, 7);
552                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
553                                                                                     backupMV.y + iDiamondSize, 8);
554                                          break;                                          break;
555    
556                                  case 4:                                  case 4:
557                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
558                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
559                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
560                                                                                     backupMV.y - iDiamondSize, 5);
561                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
562                                                                                     backupMV.y + iDiamondSize, 6);
563                                          break;                                          break;
564    
565                                  case 5:                                  case 5:
566                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
567                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
568                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
569                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
570                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
571                                                                                     backupMV.y - iDiamondSize, 5);
572                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
573                                                                                     backupMV.y + iDiamondSize, 6);
574                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
575                                                                                     backupMV.y - iDiamondSize, 7);
576                                          break;                                          break;
577    
578                                  case 6:                                  case 6:
579                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
580                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
581                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
582                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
583                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
584                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
585                                                                                     backupMV.y - iDiamondSize, 5);
586                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
587                                                                                     backupMV.y + iDiamondSize, 6);
588                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
589                                                                                     backupMV.y + iDiamondSize, 8);
590    
591                                          break;                                          break;
592    
593                                  case 7:                                  case 7:
594                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
595                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
596                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
597                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
598                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
599                                                                                     backupMV.y - iDiamondSize, 5);
600                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
601                                                                                     backupMV.y - iDiamondSize, 7);
602                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
603                                                                                     backupMV.y + iDiamondSize, 8);
604                                          break;                                          break;
605    
606                                  case 8:                                  case 8:
607                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
608                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
609                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
610                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
611                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
612                                                                                     backupMV.y + iDiamondSize, 6);
613                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
614                                                                                     backupMV.y - iDiamondSize, 7);
615                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
616                                                                                     backupMV.y + iDiamondSize, 8);
617                                          break;                                          break;
618                          default:                          default:
619                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
620                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
621                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
622                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
623                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
624                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
625                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
626                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
627                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
628                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
629                                                                                     backupMV.y - iDiamondSize, 5);
630                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
631                                                                                     backupMV.y + iDiamondSize, 6);
632                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
633                                                                                     backupMV.y - iDiamondSize, 7);
634                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
635                                                                                     backupMV.y + iDiamondSize, 8);
636                                          break;                                          break;
637                          }                          }
638                  }                  }
639          else          } else {
640                  {                  currMV->x = start_x;
641                          currMV->x = startx;                  currMV->y = start_y;
                         currMV->y = starty;  
642                  }                  }
643          return iMinSAD;          return iMinSAD;
644  }  }
645    
646    
647  int32_t Full16_MainSearch(  int32_t
648                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
649                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
650                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
651                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
652                                          const uint8_t * const cur,                                          const uint8_t * const cur,
653                                          const int x, const int y,                                    const int x,
654                                          int32_t startx, int32_t starty,                                    const int y,
655                                          int32_t iMinSAD,                                    const int start_x,
656                                      const int start_y,
657                                      int iMinSAD,
658                                          VECTOR * const currMV,                                          VECTOR * const currMV,
659                                          const VECTOR * const pmv,                                    const int center_x,
660                                          const int32_t min_dx, const int32_t max_dx,                                    const int center_y,
661                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
662                                      const int32_t max_dx,
663                                      const int32_t min_dy,
664                                      const int32_t max_dy,
665                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
666                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
667                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 772  Line 671 
671          int32_t iSAD;          int32_t iSAD;
672          int32_t dx,dy;          int32_t dx,dy;
673          VECTOR backupMV;          VECTOR backupMV;
674          backupMV.x = startx;  
675          backupMV.y = starty;          backupMV.x = start_x;
676            backupMV.y = start_y;
677    
678          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
679                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 782  Line 682 
682          return iMinSAD;          return iMinSAD;
683  }  }
684    
685  int32_t Full8_MainSearch(  int32_t
686                                          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
687                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
688                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
689                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
690                                          const uint8_t * const cur,                                          const uint8_t * const cur,
691                                          const int x, const int y,                                                  const int x,
692                                          int32_t startx, int32_t starty,                                                  const int y,
693                                          int32_t iMinSAD,                                                  const int start_xi,
694                                                    const int start_yi,
695                                                    int iMinSAD,
696                                                    VECTOR * const currMV,
697                                                    const int center_x,
698                                                    const int center_y,
699                                                    const int32_t min_dx,
700                                                    const int32_t max_dx,
701                                                    const int32_t min_dy,
702                                                    const int32_t max_dy,
703                                                    const int32_t iEdgedWidth,
704                                                    const int32_t iDiamondSize,
705                                                    const int32_t iFcode,
706                                                    const int32_t iQuant,
707                                                    int iDirection)
708    {
709    
710            int32_t iSAD;
711            int start_x = start_xi, start_y = start_yi;
712    
713    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
714    
715            if (iDirection) {
716                    CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
717                    CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
718                    CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
719                    CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
720            } else {
721                    int bDirection = 1 + 2 + 4 + 8;
722    
723                    do {
724                            iDirection = 0;
725                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
726                                    CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
727    
728                            if (bDirection & 2)
729                                    CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
730    
731                            if (bDirection & 4)
732                                    CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
733    
734                            if (bDirection & 8)
735                                    CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
736    
737                            /* now we're doing diagonal checks near our candidate */
738    
739                            if (iDirection)         //checking if anything found
740                            {
741                                    bDirection = iDirection;
742                                    iDirection = 0;
743                                    start_x = currMV->x;
744                                    start_y = currMV->y;
745                                    if (bDirection & 3)     //our candidate is left or right
746                                    {
747                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
748                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
749                                    } else                  // what remains here is up or down
750                                    {
751                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
752                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
753                                    }
754    
755                                    if (iDirection) {
756                                            bDirection += iDirection;
757                                            start_x = currMV->x;
758                                            start_y = currMV->y;
759                                    }
760                            } else                          //about to quit, eh? not so fast....
761                            {
762                                    switch (bDirection) {
763                                    case 2:
764                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
765                                                                                             start_y - iDiamondSize, 2 + 4);
766                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
767                                                                                             start_y + iDiamondSize, 2 + 8);
768                                            break;
769                                    case 1:
770    
771                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
772                                                                                             start_y - iDiamondSize, 1 + 4);
773                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
774                                                                                             start_y + iDiamondSize, 1 + 8);
775                                            break;
776                                    case 2 + 4:
777                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
778                                                                                             start_y - iDiamondSize, 1 + 4);
779                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
780                                                                                             start_y - iDiamondSize, 2 + 4);
781                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
782                                                                                             start_y + iDiamondSize, 2 + 8);
783                                            break;
784                                    case 4:
785                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
786                                                                                             start_y - iDiamondSize, 2 + 4);
787                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
788                                                                                             start_y - iDiamondSize, 1 + 4);
789                                            break;
790                                    case 8:
791                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
792                                                                                             start_y + iDiamondSize, 2 + 8);
793                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
794                                                                                             start_y + iDiamondSize, 1 + 8);
795                                            break;
796                                    case 1 + 4:
797                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
798                                                                                             start_y + iDiamondSize, 1 + 8);
799                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
800                                                                                             start_y - iDiamondSize, 1 + 4);
801                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
802                                                                                             start_y - iDiamondSize, 2 + 4);
803                                            break;
804                                    case 2 + 8:
805                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
806                                                                                             start_y - iDiamondSize, 1 + 4);
807                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
808                                                                                             start_y + iDiamondSize, 1 + 8);
809                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
810                                                                                             start_y + iDiamondSize, 2 + 8);
811                                            break;
812                                    case 1 + 8:
813                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
814                                                                                             start_y - iDiamondSize, 2 + 4);
815                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
816                                                                                             start_y + iDiamondSize, 2 + 8);
817                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
818                                                                                             start_y + iDiamondSize, 1 + 8);
819                                            break;
820                                    default:                //1+2+4+8 == we didn't find anything at all
821                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
822                                                                                             start_y - iDiamondSize, 1 + 4);
823                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
824                                                                                             start_y + iDiamondSize, 1 + 8);
825                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
826                                                                                             start_y - iDiamondSize, 2 + 4);
827                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
828                                                                                             start_y + iDiamondSize, 2 + 8);
829                                            break;
830                                    }
831                                    if (!iDirection)
832                                            break;          //ok, the end. really
833                                    else {
834                                            bDirection = iDirection;
835                                            start_x = currMV->x;
836                                            start_y = currMV->y;
837                                    }
838                            }
839                    }
840                    while (1);                              //forever
841            }
842    
843            return iMinSAD;
844    }
845    
846    int32_t
847    AdvDiamond8_MainSearch(const uint8_t * const pRef,
848                                               const uint8_t * const pRefH,
849                                               const uint8_t * const pRefV,
850                                               const uint8_t * const pRefHV,
851                                               const uint8_t * const cur,
852                                               const int x,
853                                               const int y,
854                                               const int start_xi,
855                                               const int start_yi,
856                                               int iMinSAD,
857                                          VECTOR * const currMV,                                          VECTOR * const currMV,
858                                          const VECTOR * const pmv,                                             const int center_x,
859                                          const int32_t min_dx, const int32_t max_dx,                                             const int center_y,
860                                          const int32_t min_dy, const int32_t max_dy,                                             const int32_t min_dx,
861                                               const int32_t max_dx,
862                                               const int32_t min_dy,
863                                               const int32_t max_dy,
864                                               const int32_t iEdgedWidth,
865                                               const int32_t iDiamondSize,
866                                               const int32_t iFcode,
867                                               const int32_t iQuant,
868                                               int iDirection)
869    {
870    
871            int32_t iSAD;
872            int start_x = start_xi, start_y = start_yi;
873    
874    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
875    
876            if (iDirection) {
877                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
878                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
879                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
880                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
881            } else {
882                    int bDirection = 1 + 2 + 4 + 8;
883    
884                    do {
885                            iDirection = 0;
886                            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)
887                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
888    
889                            if (bDirection & 2)
890                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
891    
892                            if (bDirection & 4)
893                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
894    
895                            if (bDirection & 8)
896                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
897    
898                            /* now we're doing diagonal checks near our candidate */
899    
900                            if (iDirection)         //checking if anything found
901                            {
902                                    bDirection = iDirection;
903                                    iDirection = 0;
904                                    start_x = currMV->x;
905                                    start_y = currMV->y;
906                                    if (bDirection & 3)     //our candidate is left or right
907                                    {
908                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
909                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
910                                    } else                  // what remains here is up or down
911                                    {
912                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
913                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
914                                    }
915    
916                                    if (iDirection) {
917                                            bDirection += iDirection;
918                                            start_x = currMV->x;
919                                            start_y = currMV->y;
920                                    }
921                            } else                          //about to quit, eh? not so fast....
922                            {
923                                    switch (bDirection) {
924                                    case 2:
925                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
926                                                                                            start_y - iDiamondSize, 2 + 4);
927                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
928                                                                                            start_y + iDiamondSize, 2 + 8);
929                                            break;
930                                    case 1:
931                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
932                                                                                            start_y - iDiamondSize, 1 + 4);
933                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
934                                                                                            start_y + iDiamondSize, 1 + 8);
935                                            break;
936                                    case 2 + 4:
937                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
938                                                                                            start_y - iDiamondSize, 1 + 4);
939                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
940                                                                                            start_y - iDiamondSize, 2 + 4);
941                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
942                                                                                            start_y + iDiamondSize, 2 + 8);
943                                            break;
944                                    case 4:
945                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
946                                                                                            start_y - iDiamondSize, 2 + 4);
947                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
948                                                                                            start_y - iDiamondSize, 1 + 4);
949                                            break;
950                                    case 8:
951                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
952                                                                                            start_y + iDiamondSize, 2 + 8);
953                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
954                                                                                            start_y + iDiamondSize, 1 + 8);
955                                            break;
956                                    case 1 + 4:
957                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
958                                                                                            start_y + iDiamondSize, 1 + 8);
959                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
960                                                                                            start_y - iDiamondSize, 1 + 4);
961                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
962                                                                                            start_y - iDiamondSize, 2 + 4);
963                                            break;
964                                    case 2 + 8:
965                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
966                                                                                            start_y - iDiamondSize, 1 + 4);
967                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
968                                                                                            start_y + iDiamondSize, 1 + 8);
969                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
970                                                                                            start_y + iDiamondSize, 2 + 8);
971                                            break;
972                                    case 1 + 8:
973                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
974                                                                                            start_y - iDiamondSize, 2 + 4);
975                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
976                                                                                            start_y + iDiamondSize, 2 + 8);
977                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
978                                                                                            start_y + iDiamondSize, 1 + 8);
979                                            break;
980                                    default:                //1+2+4+8 == we didn't find anything at all
981                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
982                                                                                            start_y - iDiamondSize, 1 + 4);
983                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
984                                                                                            start_y + iDiamondSize, 1 + 8);
985                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
986                                                                                            start_y - iDiamondSize, 2 + 4);
987                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
988                                                                                            start_y + iDiamondSize, 2 + 8);
989                                            break;
990                                    }
991                                    if (!(iDirection))
992                                            break;          //ok, the end. really
993                                    else {
994                                            bDirection = iDirection;
995                                            start_x = currMV->x;
996                                            start_y = currMV->y;
997                                    }
998                            }
999                    }
1000                    while (1);                              //forever
1001            }
1002            return iMinSAD;
1003    }
1004    
1005    
1006    int32_t
1007    Full8_MainSearch(const uint8_t * const pRef,
1008                                     const uint8_t * const pRefH,
1009                                     const uint8_t * const pRefV,
1010                                     const uint8_t * const pRefHV,
1011                                     const uint8_t * const cur,
1012                                     const int x,
1013                                     const int y,
1014                               const int start_x,
1015                               const int start_y,
1016                               int iMinSAD,
1017                               VECTOR * const currMV,
1018                               const int center_x,
1019                               const int center_y,
1020                                     const int32_t min_dx,
1021                                     const int32_t max_dx,
1022                                     const int32_t min_dy,
1023                                     const int32_t max_dy,
1024                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
1025                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
1026                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 804  Line 1030 
1030          int32_t iSAD;          int32_t iSAD;
1031          int32_t dx,dy;          int32_t dx,dy;
1032          VECTOR backupMV;          VECTOR backupMV;
1033          backupMV.x = startx;  
1034          backupMV.y = starty;          backupMV.x = start_x;
1035            backupMV.y = start_y;
1036    
1037          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
1038                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 814  Line 1041 
1041          return iMinSAD;          return iMinSAD;
1042  }  }
1043    
1044    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1045    
1046    int32_t
1047  int32_t Halfpel16_Refine(  Halfpel16_Refine(const uint8_t * const pRef,
         const uint8_t * const pRef,  
1048          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1049          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1050          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1051          const uint8_t * const cur,          const uint8_t * const cur,
1052          const int x, const int y,                                   const int x,
1053                                     const int y,
1054          VECTOR * const currMV,          VECTOR * const currMV,
1055          int32_t iMinSAD,          int32_t iMinSAD,
1056          const VECTOR * const pmv,                             const int center_x,
1057          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1058          const int32_t min_dy, const int32_t max_dy,                                   const int32_t min_dx,
1059                                     const int32_t max_dx,
1060                                     const int32_t min_dy,
1061                                     const int32_t max_dy,
1062          const int32_t iFcode,          const int32_t iFcode,
1063          const int32_t iQuant,          const int32_t iQuant,
1064          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 852  Line 1083 
1083  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1084    
1085    
1086  int32_t PMVfastSearch16(  
1087                                          const uint8_t * const pRef,  int32_t
1088    PMVfastSearch16(const uint8_t * const pRef,
1089                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1090                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1091                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1092                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1093                                          const int x, const int y,                                  const int x,
1094                                    const int y,
1095                                    const int start_x,      /* start is searched first, so it should contain the most */
1096                                    const int start_y,  /* likely motion vector for this block */
1097                                    const int center_x,     /* center is from where length of MVs is measured */
1098                                    const int center_y,
1099                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1100                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1101                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 890  Line 1127 
1127          VECTOR pmv[4];          VECTOR pmv[4];
1128          int32_t psad[4];          int32_t psad[4];
1129    
1130          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1131    
1132          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1133    
1134          static int32_t threshA,threshB;          int32_t threshA, threshB;
1135          int32_t bPredEq;          int32_t bPredEq;
1136          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1137    
1138  /* Get maximum range */  /* Get maximum range */
1139          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,
1140                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1141    
1142  /* 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 */
1143    
1144          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1145          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1146          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1147          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1148          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1149          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1150    
1151          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1152            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1153    
1154          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1155                  threshA =  512;                  threshA =  512;
1156                  threshB = 1024;                  threshB = 1024;
1157            } else {
         }  
         else  
         {  
1158                  threshA = psad[0];                  threshA = psad[0];
1159                  threshB = threshA+256;                  threshB = threshA+256;
1160                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1161                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1162                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1163                            threshA = 1024;
1164                    if (threshB > 1792)
1165                            threshB = 1792;
1166          }          }
1167    
1168          iFound=0;          iFound=0;
1169    
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
 */  
   
         if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )  
                 iDiamondSize=1; // halfpel!  
         else  
                 iDiamondSize=2; // halfpel!  
   
         if (!(MotionFlags & PMV_HALFPELDIAMOND16) )  
                 iDiamondSize*=2;  
   
1170  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1171     MinSAD=SAD     MinSAD=SAD
1172     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 957  Line 1174 
1174     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1175  */  */
1176    
1177            currMV->x = start_x;
1178            currMV->y = start_y;
1179    
1180  // Prepare for main loop          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
   
         *currMV=pmv[0];         /* current best := prediction */  
         if (!(MotionFlags & PMV_HALFPEL16 ))  
         {       /* This should NOT be necessary! */  
1181                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1182                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1183          }          }
1184    
1185          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1186                  currMV->x=max_dx;                  currMV->x=max_dx;
1187          }          }
1188          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1189                  currMV->x=min_dx;                  currMV->x=min_dx;
1190          }          }
1191          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1192                  currMV->y=max_dy;                  currMV->y=max_dy;
1193          }          }
1194          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1195                  currMV->y=min_dy;                  currMV->y=min_dy;
1196          }          }
1197    
1198          iMinSAD = sad16( cur,          iMinSAD =
1199                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1200                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1201          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1202            iMinSAD +=
1203          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1204          {                                            (uint8_t) iFcode, iQuant);
1205    
1206            if ((iMinSAD < 256) ||
1207                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1208                     ((int32_t) iMinSAD < prevMB->sad16))) {
1209                    if (iMinSAD < (int)(2 * iQuant))        // high chances for SKIP-mode
1210                    {
1211                            if (!MVzero(*currMV)) {
1212                                    iMinSAD += MV16_00_BIAS;
1213                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1214                                    iMinSAD -= MV16_00_BIAS;
1215                            }
1216                    }
1217    
1218                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1219                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 998  Line 1221 
1221                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
1222          }          }
1223    
1224    
1225    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1226       vector of the median.
1227       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1228    */
1229    
1230            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1231                    iFound = 2;
1232    
1233    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1234       Otherwise select large Diamond Search.
1235    */
1236    
1237            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1238                    iDiamondSize = 1;               // halfpel!
1239            else
1240                    iDiamondSize = 2;               // halfpel!
1241    
1242            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1243                    iDiamondSize *= 2;
1244    
1245  /*  /*
1246     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
1247     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1248     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1249     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1250  */  */
1251    
1252  // (0,0) is always possible  // (0,0) is always possible
1253    
1254            if (!MVzero(pmv[0]))
1255          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1256    
1257  // previous frame MV is always possible  // previous frame MV is always possible
1258    
1259            if (!MVzero(prevMB->mvs[0]))
1260                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1261          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1262    
1263  // left neighbour, if allowed  // left neighbour, if allowed
1264          if (x != 0)  
1265          {          if (!MVzero(pmv[1]))
1266                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1267                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1268                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1269                                            pmv[1].x = EVEN(pmv[1].x);
1270                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1271                  }                  }
1272    
1273                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1274          }          }
   
1275  // top neighbour, if allowed  // top neighbour, if allowed
1276          if (y != 0)          if (!MVzero(pmv[2]))
1277          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1278                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1279                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1280                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1281                                                    pmv[2].x = EVEN(pmv[2].x);
1282                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1283                  }                  }
1284                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1285    
1286  // top right neighbour, if allowed  // top right neighbour, if allowed
1287                  if ((uint32_t)x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1288                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1289                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1290                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1291                                                                            if (!MVequal(pmv[3], pmv[2])) {
1292                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1293                                                                                            pmv[3].x = EVEN(pmv[3].x);
1294                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1295                          }                          }
1296                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1297                                                                                                                             pmv[3].y);
1298                  }                  }
1299          }          }
1300    
1301            if ((MVzero(*currMV)) &&
1302                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1303                    iMinSAD -= MV16_00_BIAS;
1304    
1305    
1306  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1307     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.
1308  */  */
1309    
1310          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1311          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1312                     ((int32_t) iMinSAD < prevMB->sad16))) {
1313                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1314                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1315                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1065  Line 1327 
1327     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1328  */  */
1329    
1330            if (MotionFlags & PMV_USESQUARES16)
1331                    MainSearchPtr = Square16_MainSearch;
1332            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1333                    MainSearchPtr = AdvDiamond16_MainSearch;
1334            else
1335                    MainSearchPtr = Diamond16_MainSearch;
1336    
1337          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1338    
1339    
1340  /* 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 */
1341          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1342                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1343                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1344                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1345                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1346                                                      iQuant, iFound);
1347    
1348          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1349                  *currMV = newMV;                  *currMV = newMV;
1350                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1351          }          }
1352    
1353          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1354  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1355    
1356                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1357                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1358                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1359                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1360                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1361                                                                      iDiamondSize, iFcode, iQuant, iFound);
1362    
1363                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1364                          *currMV = newMV;                          *currMV = newMV;
1365                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1366                  }                  }
1367                  }                  }
1368    
1369                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1370                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1371                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1372                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1373                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1374                                                                      iEdgedWidth, iDiamondSize, iFcode,
1375                                                                      iQuant, iFound);
1376    
1377                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1378                          *currMV = newMV;                          *currMV = newMV;
1379                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1380                  }                  }
# Line 1114  Line 1385 
1385     Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.     Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
1386  */  */
1387    
1388  PMVfast16_Terminate_with_Refine:    PMVfast16_Terminate_with_Refine:
1389          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
1390                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1391                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1392                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1393                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1394    
1395      PMVfast16_Terminate_without_Refine:
1396            currPMV->x = currMV->x - center_x;
1397            currPMV->y = currMV->y - center_y;
1398            return iMinSAD;
1399    }
1400    
1401    
1402    
1403    
1404    
1405    
1406    int32_t
1407    Diamond8_MainSearch(const uint8_t * const pRef,
1408                                            const uint8_t * const pRefH,
1409                                            const uint8_t * const pRefV,
1410                                            const uint8_t * const pRefHV,
1411                                            const uint8_t * const cur,
1412                                            const int x,
1413                                            const int y,
1414                                            const int32_t start_x,
1415                                            const int32_t start_y,
1416                                            int32_t iMinSAD,
1417                                            VECTOR * const currMV,
1418                                            const int center_x,
1419                                            const int center_y,
1420                                            const int32_t min_dx,
1421                                            const int32_t max_dx,
1422                                            const int32_t min_dy,
1423                                            const int32_t max_dy,
1424                                            const int32_t iEdgedWidth,
1425                                            const int32_t iDiamondSize,
1426                                            const int32_t iFcode,
1427                                            const int32_t iQuant,
1428                                            int iFound)
1429    {
1430    /* Do a diamond search around given starting point, return SAD of best */
1431    
1432            int32_t iDirection = 0;
1433            int32_t iDirectionBackup;
1434            int32_t iSAD;
1435            VECTOR backupMV;
1436    
1437            backupMV.x = start_x;
1438            backupMV.y = start_y;
1439    
1440    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1441    
1442            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1443            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1444            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1445            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1446    
1447            if (iDirection) {
1448                    while (!iFound) {
1449                            iFound = 1;
1450                            backupMV = *currMV;     // since iDirection!=0, this is well defined!
1451                            iDirectionBackup = iDirection;
1452    
1453  PMVfast16_Terminate_without_Refine:                          if (iDirectionBackup != 2)
1454          currPMV->x = currMV->x - pmv[0].x;                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1455          currPMV->y = currMV->y - pmv[0].y;                                                                                    backupMV.y, 1);
1456                            if (iDirectionBackup != 1)
1457                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1458                                                                                      backupMV.y, 2);
1459                            if (iDirectionBackup != 4)
1460                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1461                                                                                      backupMV.y - iDiamondSize, 3);
1462                            if (iDirectionBackup != 3)
1463                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1464                                                                                      backupMV.y + iDiamondSize, 4);
1465                    }
1466            } else {
1467                    currMV->x = start_x;
1468                    currMV->y = start_y;
1469            }
1470          return iMinSAD;          return iMinSAD;
1471  }  }
1472    
1473    
1474    
1475    
1476    int32_t
1477    Square8_MainSearch(const uint8_t * const pRef,
 int32_t Diamond8_MainSearch(  
         const uint8_t * const pRef,  
1478          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1479          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1480          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1481          const uint8_t * const cur,          const uint8_t * const cur,
1482          const int x, const int y,                                     const int x,
1483          int32_t startx, int32_t starty,                                     const int y,
1484                                       const int32_t start_x,
1485                                       const int32_t start_y,
1486          int32_t iMinSAD,          int32_t iMinSAD,
1487          VECTOR * const currMV,          VECTOR * const currMV,
1488          const VECTOR * const pmv,                                     const int center_x,
1489          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
1490          const int32_t min_dy, const int32_t max_dy,                                     const int32_t min_dx,
1491                                       const int32_t max_dx,
1492                                       const int32_t min_dy,
1493                                       const int32_t max_dy,
1494          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1495          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1496          const int32_t iFcode,          const int32_t iFcode,
1497          const int32_t iQuant,          const int32_t iQuant,
1498          int iFound)          int iFound)
1499  {  {
1500  /* Do a diamond search around given starting point, return SAD of best */  /* Do a square search around given starting point, return SAD of best */
1501    
1502          int32_t iDirection=0;          int32_t iDirection=0;
1503          int32_t iSAD;          int32_t iSAD;
1504          VECTOR backupMV;          VECTOR backupMV;
         backupMV.x = startx;  
         backupMV.y = starty;  
1505    
1506  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */          backupMV.x = start_x;
1507            backupMV.y = start_y;
1508    
1509    /* It's one search with full square pattern, and new parts for all following diamonds */
1510    
1511    /*   new direction are extra, so 1-4 is normal diamond
1512          537
1513          1*2
1514          648
1515    */
1516    
1517          CHECK_MV8_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);          CHECK_MV8_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
1518          CHECK_MV8_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);          CHECK_MV8_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
1519          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1520          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1521    
1522          if (iDirection)          CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1523                  while (!iFound)                                                           backupMV.y - iDiamondSize, 5);
1524                  {          CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1525                                                             backupMV.y + iDiamondSize, 6);
1526            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1527                                                             backupMV.y - iDiamondSize, 7);
1528            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1529                                                             backupMV.y + iDiamondSize, 8);
1530    
1531    
1532            if (iDirection) {
1533                    while (!iFound) {
1534                          iFound = 1;                          iFound = 1;
1535                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV = *currMV;
1536    
1537                            switch (iDirection) {
1538                            case 1:
1539                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1540                                                                                       backupMV.y, 1);
1541                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1542                                                                                     backupMV.y - iDiamondSize, 5);
1543                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1544                                                                                     backupMV.y - iDiamondSize, 7);
1545                                    break;
1546                            case 2:
1547                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1548                                                                                     2);
1549                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1550                                                                                     backupMV.y + iDiamondSize, 6);
1551                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1552                                                                                     backupMV.y + iDiamondSize, 8);
1553                                    break;
1554    
1555                            case 3:
1556                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1557                                                                                     4);
1558                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1559                                                                                     backupMV.y - iDiamondSize, 7);
1560                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1561                                                                                     backupMV.y + iDiamondSize, 8);
1562                                    break;
1563    
1564                            case 4:
1565                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1566                                                                                     3);
1567                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1568                                                                                     backupMV.y - iDiamondSize, 5);
1569                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1570                                                                                     backupMV.y + iDiamondSize, 6);
1571                                    break;
1572    
1573                            case 5:
1574                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1575                                                                                     1);
1576                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1577                                                                                     3);
1578                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1579                                                                                     backupMV.y - iDiamondSize, 5);
1580                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1581                                                                                     backupMV.y + iDiamondSize, 6);
1582                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1583                                                                                     backupMV.y - iDiamondSize, 7);
1584                                    break;
1585    
1586                            case 6:
1587                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1588                                                                                     2);
1589                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1590                                                                                     3);
1591    
1592                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1593                                                                                     backupMV.y - iDiamondSize, 5);
1594                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1595                                                                                     backupMV.y + iDiamondSize, 6);
1596                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1597                                                                                     backupMV.y + iDiamondSize, 8);
1598    
1599                                    break;
1600    
1601                          if ( iDirection != 2)                          case 7:
1602                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1603                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
1604                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1605                          if ( iDirection != 4)                                                                                   4);
1606                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1607                          if ( iDirection != 3)                                                                                   backupMV.y - iDiamondSize, 5);
1608                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1609                                                                                     backupMV.y - iDiamondSize, 7);
1610                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1611                                                                                     backupMV.y + iDiamondSize, 8);
1612                                    break;
1613    
1614                            case 8:
1615                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1616                                                                                     2);
1617                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1618                                                                                     4);
1619                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1620                                                                                     backupMV.y + iDiamondSize, 6);
1621                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1622                                                                                     backupMV.y - iDiamondSize, 7);
1623                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1624                                                                                     backupMV.y + iDiamondSize, 8);
1625                                    break;
1626                            default:
1627                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1628                                                                                     1);
1629                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1630                                                                                     2);
1631                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1632                                                                                     3);
1633                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1634                                                                                     4);
1635    
1636                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1637                                                                                     backupMV.y - iDiamondSize, 5);
1638                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1639                                                                                     backupMV.y + iDiamondSize, 6);
1640                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1641                                                                                     backupMV.y - iDiamondSize, 7);
1642                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1643                                                                                     backupMV.y + iDiamondSize, 8);
1644                                    break;
1645                  }                  }
1646          else                  }
1647          {          } else {
1648                  currMV->x = startx;                  currMV->x = start_x;
1649                  currMV->y = starty;                  currMV->y = start_y;
1650          }          }
1651          return iMinSAD;          return iMinSAD;
1652  }  }
1653    
1654  int32_t Halfpel8_Refine(  
1655          const uint8_t * const pRef,  
1656    
1657    
1658    int32_t
1659    Halfpel8_Refine_c(const uint8_t * const pRef,
1660          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1661          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1662          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1663          const uint8_t * const cur,          const uint8_t * const cur,
1664          const int x, const int y,                                    const int x,
1665                                      const int y,
1666          VECTOR * const currMV,          VECTOR * const currMV,
1667          int32_t iMinSAD,          int32_t iMinSAD,
1668          const VECTOR * const pmv,                                    const int center_x,
1669          const int32_t min_dx, const int32_t max_dx,                                    const int center_y,
1670          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
1671                                      const int32_t max_dx,
1672                                      const int32_t min_dy,
1673                                      const int32_t max_dy,
1674          const int32_t iFcode,          const int32_t iFcode,
1675          const int32_t iQuant,          const int32_t iQuant,
1676          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1225  Line 1695 
1695    
1696  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1697    
1698  int32_t PMVfastSearch8(  int32_t
1699                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1700                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1701                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1702                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1703                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1704                                          const int x, const int y,                             const int x,
1705                                          const int start_x, const int start_y,                             const int y,
1706                               const int start_x,
1707                               const int start_y,
1708                                    const int center_x,
1709                                    const int center_y,
1710                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1711                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1712                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1260  Line 1734 
1734          int32_t psad[4];          int32_t psad[4];
1735          VECTOR newMV;          VECTOR newMV;
1736          VECTOR backupMV;          VECTOR backupMV;
1737            VECTOR startMV;
1738    
1739          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1740          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1741    
1742          static int32_t threshA,threshB;           int32_t threshA, threshB;
1743          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1744          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1745    
1746          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1747    
1748  /* Get maximum range */          MainSearch8FuncPtr MainSearchPtr;
         get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                   x, y, 8, iWidth, iHeight, iFcode);  
1749    
1750  /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */          /* Init variables */
1751            startMV.x = start_x;
1752            startMV.y = start_y;
1753    
1754          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          /* Get maximum range */
1755          { min_dx = EVEN(min_dx);          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
1756                              iFcode);
1757    
1758            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
1759                    min_dx = EVEN(min_dx);
1760          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1761          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1762          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1763          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
1764    
1765          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1766            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
1767    
1768          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1769                  threshA =  512/4;                  threshA =  512/4;
1770                  threshB = 1024/4;                  threshB = 1024/4;
1771    
1772          }          } else {
1773          else                  threshA = psad[0] / 4;  /* good estimate? */
         {  
                 threshA = psad[0]/4;                    /* good estimate */  
1774                  threshB = threshA+256/4;                  threshB = threshA+256/4;
1775                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
1776                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
1777                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
1778                            threshA = 1024 / 4;
1779                    if (threshB > 1792 / 4)
1780                            threshB = 1792 / 4;
1781          }          }
1782    
1783          iFound=0;          iFound=0;
1784    
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
 */  
   
         if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )  
                 iDiamondSize=1; // 1 halfpel!  
         else  
                 iDiamondSize=2; // 2 halfpel = 1 full pixel!  
   
         if (!(MotionFlags & PMV_HALFPELDIAMOND8) )  
                 iDiamondSize*=2;  
   
1785  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1786     MinSAD=SAD     MinSAD=SAD
1787     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 1333  Line 1792 
1792    
1793  // Prepare for main loop  // Prepare for main loop
1794    
1795          currMV->x=start_x;              /* start with mv16 */    if (MotionFlags & PMV_USESQUARES8)
1796          currMV->y=start_y;        MainSearchPtr = Square8_MainSearch;
1797      else
1798    
1799          iMinSAD = sad8( cur,          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1800                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  MainSearchPtr = AdvDiamond8_MainSearch;
1801                          iEdgedWidth);          else
1802          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;                  MainSearchPtr = Diamond8_MainSearch;
1803    
1804          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )  
1805          {          *currMV = startMV;
1806    
1807            iMinSAD =
1808                    sad8(cur,
1809                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
1810                                                    iEdgedWidth), iEdgedWidth);
1811            iMinSAD +=
1812                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
1813                                             (uint8_t) iFcode, iQuant);
1814    
1815            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
1816                                                                    && ((int32_t) iMinSAD <
1817                                                                            prevMB->sad8[iSubBlock]))) {
1818                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1819                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1820                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1821                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
1822          }          }
1823    
1824    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1825       vector of the median.
1826       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1827    */
1828    
1829            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
1830                    iFound = 2;
1831    
1832    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1833       Otherwise select large Diamond Search.
1834    */
1835    
1836            if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
1837                    iDiamondSize = 1;               // 1 halfpel!
1838            else
1839                    iDiamondSize = 2;               // 2 halfpel = 1 full pixel!
1840    
1841            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1842                    iDiamondSize *= 2;
1843    
1844    
1845  /*  /*
1846     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
1847     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1848     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1849     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1850  */  */
1851    
1852  // the prediction might be even better than mv16  // the median prediction might be even better than mv16
         CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);  
1853    
1854  // (0,0) is always possible          if (!MVequal(pmv[0], startMV))
1855                    CHECK_MV8_CANDIDATE(center_x, center_y);
1856    
1857    // (0,0) if needed
1858            if (!MVzero(pmv[0]))
1859                    if (!MVzero(startMV))
1860          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1861    
1862  // previous frame MV is always possible  // previous frame MV if needed
1863          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
1864                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
1865                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
1866                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
1867                                                                            prevMB->mvs[iSubBlock].y);
1868    
1869            if ((iMinSAD <= threshA) ||
1870                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1871                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1872                    if (MotionFlags & PMV_QUICKSTOP16)
1873                            goto PMVfast8_Terminate_without_Refine;
1874                    if (MotionFlags & PMV_EARLYSTOP16)
1875                            goto PMVfast8_Terminate_with_Refine;
1876            }
1877    
1878  // left neighbour, if allowed  // left neighbour, if allowed and needed
1879          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
1880          {                  if (!MVequal(pmv[1], startMV))
1881                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
1882                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
1883                                            if (!(MotionFlags & PMV_HALFPEL8)) {
1884                                                    pmv[1].x = EVEN(pmv[1].x);
1885                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1886                  }                  }
1887                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1888          }          }
1889    // top neighbour, if allowed and needed
1890  // top neighbour, if allowed          if (!MVzero(pmv[2]))
1891          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
1892          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
1893                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
1894                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
1895                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
1896                                                            pmv[2].x = EVEN(pmv[2].x);
1897                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1898                  }                  }
1899                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1900    
1901  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
1902                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
1903                  {                                                          if (!MVequal(pmv[3], startMV))
1904                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
1905                          {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
1906                                                                                    if (!MVequal(pmv[3], pmv[1]))
1907                                                                                            if (!MVequal(pmv[3], pmv[2])) {
1908                                                                                                    if (!
1909                                                                                                            (MotionFlags &
1910                                                                                                             PMV_HALFPEL8)) {
1911                                                                                                            pmv[3].x = EVEN(pmv[3].x);
1912                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1913                          }                          }
1914                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
1915                                                                                                                                            pmv[3].y);
1916                  }                  }
1917          }          }
1918    
1919            if ((MVzero(*currMV)) &&
1920                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1921                    iMinSAD -= MV8_00_BIAS;
1922    
1923    
1924  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1925     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.
1926  */  */
1927    
1928          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
1929          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1930                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1931                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1932                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1933                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1421  Line 1947 
1947          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1948    
1949  /* 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 */
1950          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1951                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
1952                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
1953                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1954                                                      iQuant, iFound);
1955    
1956          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1957                  *currMV = newMV;                  *currMV = newMV;
1958                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1959          }          }
1960    
1961          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
1962  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1963    
1964                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1965                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1966                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1967                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
1968                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1969                                                                      iDiamondSize, iFcode, iQuant, iFound);
1970    
1971                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1972                          *currMV = newMV;                          *currMV = newMV;
1973                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1974                  }                  }
1975                  }                  }
1976    
1977                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1978                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1979                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1980                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
1981                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
1982                                                                      iQuant, iFound);
1983    
1984                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1985                          *currMV = newMV;                          *currMV = newMV;
1986                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1987                  }                  }
# Line 1469  Line 1994 
1994    
1995  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
1996          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1997                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1998                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1999                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2000                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2001    
2002    
2003  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
2004          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2005          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2006    
2007          return iMinSAD;          return iMinSAD;
2008  }  }
2009    
2010  int32_t EPZSSearch16(  int32_t
2011                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2012                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2013                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2014                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2015                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2016                                          const int x, const int y,                           const int x,
2017                             const int y,
2018                            const int start_x,
2019                            const int start_y,
2020                            const int center_x,
2021                            const int center_y,
2022                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2023                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2024                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1519  Line 2049 
2049          int32_t psad[8];          int32_t psad[8];
2050    
2051          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2052          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
2053    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2054          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
2055          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
2056    
2057          static int32_t thresh2;           int32_t thresh2;
2058          int32_t bPredEq;          int32_t bPredEq;
2059          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2060    
2061          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2062    
2063          if (oldMBs == NULL)          if (oldMBs == NULL) {
2064          {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2065                  fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2066          }          }
2067          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2068    
2069  /* Get maximum range */  /* Get maximum range */
2070          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,
2071                          x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
   
 /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  
2072    
2073          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
2074          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2075            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2076            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2077            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2078          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2079            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2080          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2081    
2082  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2083          MinSAD=SAD          MinSAD=SAD
# Line 1559  Line 2088 
2088    
2089  // Prepare for main loop  // Prepare for main loop
2090    
2091          *currMV=pmv[0];         /* current best := median prediction */          currMV->x = start_x;
2092          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2093          {  
2094            if (!(MotionFlags & PMV_HALFPEL16)) {
2095                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2096                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2097          }          }
# Line 1577  Line 2107 
2107    
2108  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2109    
2110          iMinSAD = sad16( cur,          iMinSAD =
2111                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2112                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2113          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2114            iMinSAD +=
2115                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2116                                              (uint8_t) iFcode, iQuant);
2117    
2118  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2119          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD < 256) ||
2120                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2121                     ((int32_t) iMinSAD < prevMB->sad16))) {
2122                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2123                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2124                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1594  Line 2128 
2128  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2129    
2130  // previous frame MV  // previous frame MV
2131          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
2132    
2133  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2134  // 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
2135    
2136          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2137                  thresh2 =  512;                  thresh2 =  512;
2138          }          } else {
         else  
         {  
2139  /* 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] */
2140    
2141                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1616  Line 2147 
2147    
2148    
2149  // left neighbour, if allowed  // left neighbour, if allowed
2150          if (x != 0)          if (x != 0) {
2151          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2152                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2153                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2154                  }                  }
2155                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2156          }          }
   
2157  // top neighbour, if allowed  // top neighbour, if allowed
2158          if (y != 0)          if (y != 0) {
2159          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2160                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2161                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2162                  }                  }
2163                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
2164    
2165  // top right neighbour, if allowed  // top right neighbour, if allowed
2166                  if ((uint32_t)x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
2167                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2168                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2169                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2170                          }                          }
2171                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1650  Line 2177 
2177  */  */
2178    
2179          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2180                  || ( MVequal(*currMV,pMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2181                  {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2182                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2183                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2184                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1660  Line 2187 
2187    
2188  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
2189    
2190          backupMV = pMB->mvs[0];                 // last MV          backupMV = prevMB->mvs[0];      // collocated MV
2191          backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X          backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2192          backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y          backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2193    
2194          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
2195    
2196  // left neighbour  // left neighbour
2197          if (x != 0)          if (x != 0)
2198                  CHECK_MV16_CANDIDATE((oldMB-1)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - 1)->mvs[0].x, (prevMB - 1)->mvs[0].y);
2199    
2200  // top neighbour  // top neighbour
2201          if (y != 0)          if (y != 0)
2202                  CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2203                                                             (prevMB - iWcount)->mvs[0].y);
2204    
2205  // 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
2206    
2207          if ((uint32_t)x != iWcount-1)          if ((uint32_t)x != iWcount-1)
2208                  CHECK_MV16_CANDIDATE((pMB+1)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + 1)->mvs[0].x, (prevMB + 1)->mvs[0].y);
2209    
2210  // bottom neighbour, dito  // bottom neighbour, dito
2211          if ((uint32_t)y != iHcount-1)          if ((uint32_t)y != iHcount-1)
2212                  CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2213                                                             (prevMB + iWcount)->mvs[0].y);
2214    
2215  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2216          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2) {
                 {  
2217                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2218                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2219                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1696  Line 2224 
2224    
2225          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2226    
 /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  
   
2227          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
2228                  EPZSMainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
2229          else          else
2230                  EPZSMainSearchPtr = Diamond16_MainSearch;           if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2231                    MainSearchPtr = AdvDiamond16_MainSearch;
2232            else
2233                    MainSearchPtr = Diamond16_MainSearch;
2234    
2235          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
                         x, y,  
                         currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,  
                         2, iFcode, iQuant, 0);  
2236    
2237          if (iSAD < iMinSAD)          iSAD =
2238          {                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2239                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2240                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2241    
2242            if (iSAD < iMinSAD) {
2243                  *currMV = newMV;                  *currMV = newMV;
2244                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2245          }          }
2246    
2247    
2248          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
2249  /* 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) */
2250    
2251                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2252                  {                          iSAD =
2253                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2254                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2255                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2256                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2257                  }                  }
2258    
2259                  if (iSAD < iMinSAD)                  if (iSAD < iMinSAD) {
                 {  
2260                          *currMV = newMV;                          *currMV = newMV;
2261                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2262                  }                  }
2263    
2264                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2265                  {                          iSAD =
2266                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2267                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2268                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
                         pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, /*iDiamondSize*/ 2, iFcode, iQuant, 0);  
2269    
2270                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2271                                  *currMV = newMV;                                  *currMV = newMV;
2272                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2273                          }                          }
# Line 1752  Line 2278 
2278    
2279  EPZS16_Terminate_with_Refine:  EPZS16_Terminate_with_Refine:
2280          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
2281                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2282                                  x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2283                                  currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2284                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
2285    
2286  EPZS16_Terminate_without_Refine:  EPZS16_Terminate_without_Refine:
2287    
2288          *oldMB = *pMB;          *oldMB = *prevMB;
2289    
2290          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2291          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2292          return iMinSAD;          return iMinSAD;
2293  }  }
2294    
2295    
2296  int32_t EPZSSearch8(  int32_t
2297                                          const uint8_t * const pRef,  EPZSSearch8(const uint8_t * const pRef,
2298                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2299                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2300                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2301                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2302                                          const int x, const int y,                          const int x,
2303                                          const int start_x, const int start_y,                          const int y,
2304                            const int start_x,
2305                            const int start_y,
2306                            const int center_x,
2307                            const int center_y,
2308                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2309                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2310                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1784  Line 2314 
2314                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2315                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2316  {  {
2317    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
2318    
2319      const uint32_t iWcount = pParam->mb_width;      const uint32_t iWcount = pParam->mb_width;
2320          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2321          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
# Line 1806  Line 2338 
2338    
2339          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
2340    
2341          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2342          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
2343    
2344          int32_t bPredEq;          int32_t bPredEq;
2345          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2346    
2347          MainSearch8FuncPtr EPZSMainSearchPtr;          MainSearch8FuncPtr MainSearchPtr;
2348    
2349  /* Get maximum range */  /* Get maximum range */
2350          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,
2351                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2352    
2353  /* 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 */
2354    
2355          if (!(MotionFlags & PMV_HALFPEL8 ))          if (!(MotionFlags & PMV_HALFPEL8)) {
2356          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2357            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2358            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2359            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2360          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2361            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2362          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2363    
2364    
2365  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 1840  Line 2372 
2372  // Prepare for main loop  // Prepare for main loop
2373    
2374    
2375          if (!(MotionFlags & PMV_HALFPEL8))          if (!(MotionFlags & PMV_HALFPEL8)) {
         {  
2376                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2377                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2378          }          }
# Line 1858  Line 2389 
2389  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2390    
2391    
2392          iMinSAD = sad8( cur,          iMinSAD =
2393                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2394                  iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2395          iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                  iEdgedWidth), iEdgedWidth);
2396            iMinSAD +=
2397                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2398                                             (uint8_t) iFcode, iQuant);
2399    
2400    
2401  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2402          if (iMinSAD < 256/4 )          if (iMinSAD < 256 / 4) {
                 {  
2403                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2404                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2405                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 1875  Line 2408 
2408    
2409  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2410    
 // previous frame MV  
         CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
2411    
2412  // MV=(0,0) is often a good choice  // MV=(0,0) is often a good choice
   
2413          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2414    
2415    // previous frame MV
2416            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2417    
2418    // left neighbour, if allowed
2419            if (psad[1] != MV_MAX_ERROR) {
2420                    if (!(MotionFlags & PMV_HALFPEL8)) {
2421                            pmv[1].x = EVEN(pmv[1].x);
2422                            pmv[1].y = EVEN(pmv[1].y);
2423                    }
2424                    CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2425            }
2426    // top neighbour, if allowed
2427            if (psad[2] != MV_MAX_ERROR) {
2428                    if (!(MotionFlags & PMV_HALFPEL8)) {
2429                            pmv[2].x = EVEN(pmv[2].x);
2430                            pmv[2].y = EVEN(pmv[2].y);
2431                    }
2432                    CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2433    
2434    // top right neighbour, if allowed
2435                    if (psad[3] != MV_MAX_ERROR) {
2436                            if (!(MotionFlags & PMV_HALFPEL8)) {
2437                                    pmv[3].x = EVEN(pmv[3].x);
2438                                    pmv[3].y = EVEN(pmv[3].y);
2439                            }
2440                            CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2441                    }
2442            }
2443    
2444    /*  // this bias is zero anyway, at the moment!
2445    
2446            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2447                    iMinSAD -= MV8_00_BIAS;
2448    
2449    */
2450    
2451  /* Terminate if MinSAD <= T_2  /* Terminate if MinSAD <= T_2
2452     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]
2453  */  */
2454    
2455          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
                 {  
2456                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2457                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2458                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
2459                                  goto EPZS8_Terminate_with_Refine;                                  goto EPZS8_Terminate_with_Refine;
2460                  }                  }
2461    
2462  /************ (if Diamond Search)  **************/  /************ (Diamond Search)  **************/
2463    
2464          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2465    
2466          if (!(MotionFlags & PMV_HALFPELDIAMOND8))          if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2467                  iDiamondSize *= 2;                  iDiamondSize *= 2;
2468    
2469  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2470    
2471  //      if (MotionFlags & PMV_USESQUARES8)  // there is no EPZS^2 for inter4v at the moment
 //              EPZSMainSearchPtr = Square8_MainSearch;  
 //      else  
                 EPZSMainSearchPtr = Diamond8_MainSearch;  
   
         iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,  
                 x, y,  
                 currMV->x, currMV->y, iMinSAD, &newMV,  
                 pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,  
                 iDiamondSize, iFcode, iQuant, 00);  
2472    
2473      if (MotionFlags & PMV_USESQUARES8)
2474          MainSearchPtr = Square8_MainSearch;
2475      else
2476    
2477          if (iSAD < iMinSAD)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2478          {                  MainSearchPtr = AdvDiamond8_MainSearch;
2479            else
2480                    MainSearchPtr = Diamond8_MainSearch;
2481    
2482            iSAD =
2483                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2484                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2485                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2486                                                      iQuant, 0);
2487    
2488    
2489            if (iSAD < iMinSAD) {
2490                  *currMV = newMV;                  *currMV = newMV;
2491                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2492          }          }
2493    
2494          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2495  /* 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) */
2496    
2497                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2498                  {                          iSAD =
2499                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2500                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2501                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2502                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2503    
2504                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2505                                  *currMV = newMV;                                  *currMV = newMV;
2506                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2507                          }                          }
2508                  }                  }
2509    
2510                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2511                  {                          iSAD =
2512                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2513                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2514                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2515                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, 0);
2516    
2517                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2518                                  *currMV = newMV;                                  *currMV = newMV;
2519                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2520                          }                          }
# Line 1958  Line 2525 
2525    
2526  EPZS8_Terminate_with_Refine:  EPZS8_Terminate_with_Refine:
2527          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2528                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2529                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2530                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2531                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2532    
2533  EPZS8_Terminate_without_Refine:  EPZS8_Terminate_without_Refine:
2534    
2535          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2536          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2537          return iMinSAD;          return iMinSAD;
2538  }  }
   
   
   
   
   
 /* ***********************************************************  
         bvop motion estimation  
 // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)  
 ***************************************************************/  
   
 /*  
 void MotionEstimationBVOP(  
                         MBParam * const pParam,  
                         FRAMEINFO * const frame,  
   
                         // forward (past) reference  
                         const MACROBLOCK * const f_mbs,  
                     const IMAGE * const f_ref,  
                         const IMAGE * const f_refH,  
                     const IMAGE * const f_refV,  
                         const IMAGE * const f_refHV,  
                         // backward (future) reference  
                         const MACROBLOCK * const b_mbs,  
                     const IMAGE * const b_ref,  
                         const IMAGE * const b_refH,  
                     const IMAGE * const b_refV,  
                         const IMAGE * const b_refHV)  
 {  
     const uint32_t mb_width = pParam->mb_width;  
     const uint32_t mb_height = pParam->mb_height;  
         const int32_t edged_width = pParam->edged_width;  
   
         int32_t i,j;  
   
         int32_t f_sad16;  
         int32_t b_sad16;  
         int32_t i_sad16;  
         int32_t d_sad16;  
         int32_t best_sad;  
   
         VECTOR pmv_dontcare;  
   
         // note: i==horizontal, j==vertical  
     for (j = 0; j < mb_height; j++)  
         {  
                 for (i = 0; i < mb_width; i++)  
                 {  
                         MACROBLOCK *mb = &frame->mbs[i + j*mb_width];  
                         const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];  
                         const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];  
   
                         if (b_mb->mode == MODE_INTER  
                                 && b_mb->cbp == 0  
                                 && b_mb->mvs[0].x == 0  
                                 && b_mb->mvs[0].y == 0)  
                         {  
                                 mb->mode = MB_IGNORE;  
                                 mb->mvs[0].x = 0;  
                                 mb->mvs[0].y = 0;  
                                 mb->b_mvs[0].x = 0;  
                                 mb->b_mvs[0].y = 0;  
                                 continue;  
                         }  
   
   
                         // forward search  
                         f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,  
                                                 &frame->image,  
                                                 i, j,  
                                                 frame->motion_flags,  frame->quant, frame->fcode,  
                                                 pParam,  
                                                 f_mbs,  
                                                 &mb->mvs[0], &pmv_dontcare);    // ignore pmv  
   
                         // backward search  
                         b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,  
                                                 &frame->image,  
                                                 i, j,  
                                                 frame->motion_flags,  frame->quant, frame->bcode,  
                                                 pParam,  
                                                 b_mbs,  
                                                 &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv  
   
                         // interpolate search (simple, but effective)  
                         i_sad16 = sad16bi_c(  
                                         frame->image.y + i*16 + j*16*edged_width,  
                                         get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,  
                                                 i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),  
                                         get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,  
                                                 i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),  
                                         edged_width);  
   
                         // TODO: direct search  
                         // predictor + range of [-32,32]  
                         d_sad16 = 65535;  
   
   
                         if (f_sad16 < b_sad16)  
                         {  
                                 best_sad = f_sad16;  
                                 mb->mode = MB_FORWARD;  
                         }  
                         else  
                         {  
                                 best_sad = b_sad16;  
                                 mb->mode = MB_BACKWARD;  
                         }  
   
                         if (i_sad16 < best_sad)  
                         {  
                                 best_sad = i_sad16;  
                                 mb->mode = MB_INTERPOLATE;  
                         }  
   
                         if (d_sad16 < best_sad)  
                         {  
                                 best_sad = d_sad16;  
                                 mb->mode = MB_DIRECT;  
                         }  
   
                 }  
         }  
 }  
   
 */  

Legend:
Removed from v.136  
changed lines
  Added in v.524

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