[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 476, Thu Sep 12 18:53:11 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);  
   
   
 int32_t PMVfastSearch8(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const int start_x, const int start_y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
 int32_t EPZSSearch8(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const int start_x, const int start_y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
47    
 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);  
48    
49  typedef MainSearch16Func* MainSearch16FuncPtr;  static int32_t lambda_vec16[32] =       /* rounded values for lambda param for weight of motion bits as in modified H.26L */
50    { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),
51                    (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),
52            (int) (1.89187 + 0.5), (int) (2.11542 + 0.5), (int) (2.35878 + 0.5),
53                    (int) (2.62429 + 0.5), (int) (2.91455 + 0.5),
54            (int) (3.23253 + 0.5), (int) (3.58158 + 0.5), (int) (3.96555 + 0.5),
55                    (int) (4.38887 + 0.5), (int) (4.85673 + 0.5),
56            (int) (5.37519 + 0.5), (int) (5.95144 + 0.5), (int) (6.59408 + 0.5),
57                    (int) (7.31349 + 0.5), (int) (8.12242 + 0.5),
58            (int) (9.03669 + 0.5), (int) (10.0763 + 0.5), (int) (11.2669 + 0.5),
59                    (int) (12.6426 + 0.5), (int) (14.2493 + 0.5),
60            (int) (16.1512 + 0.5), (int) (18.442 + 0.5), (int) (21.2656 + 0.5),
61                    (int) (24.8580 + 0.5), (int) (29.6436 + 0.5),
62            (int) (36.4949 + 0.5)
63    };
64    
65    static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now */
66    
 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);  
67    
 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);  
                 }  
         */  
155    
156          // note: i==horizontal, j==vertical                          if (pMB->mode == MODE_NOT_CODED)
157          for (i = 0; i < iHcount; i++)                                  continue;
                 for (j = 0; j < iWcount; j++)  
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
                         MACROBLOCK *prevMB = &prevMBs[j + i * iWcount];  
158    
159                          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;  
160    
161                            pMB->sad16 =
162                                    SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
163                                                     x, y, predMV.x, predMV.y, predMV.x, predMV.y,
164                                                     current->motion_flags, current->quant,
165                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
166                                                     &pMB->pmvs[0]);
167    
168                          /* decide: MODE_INTER or MODE_INTRA                          if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
169                             if (dev_intra < sad_inter - 2 * nb) use_intra                                  int32_t deviation;
                         */  
170    
171                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                                  deviation =
172                                            dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
173                                                      pParam->edged_width);
174    
175                          if (deviation < (sad16 - INTER_BIAS))                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
                         {  
176                                  pMB->mode = MODE_INTRA;                                  pMB->mode = MODE_INTRA;
177                                  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] =
178                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                                  pMB->mvs[3] = zeroMV;
179                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
180                                  pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
181    
182                                  iIntra++;                                  iIntra++;
183                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 340  Line 185 
185    
186                                  continue;                                  continue;
187                          }                          }
188                            }
189    
190                            pmv = pMB->pmvs[0];
191                          if (current->global_flags & XVID_INTER4V)                          if (current->global_flags & XVID_INTER4V)
192                          {                                  if ((!(current->global_flags & XVID_LUMIMASKING) ||
193                                  pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                           pMB->dquant == NO_CHANGE)) {
194                                                         2 * j, 2 * i, mv16.x, mv16.y,                                          int32_t sad8 = IMV16X16 * current->quant;
195                                                             current->motion_flags, current->quant, current->fcode,  
196                                                         pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);                                          if (sad8 < pMB->sad16) {
197                                                    sad8 += pMB->sad8[0] =
198                                  pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
199                                                         2 * j + 1, 2 * i, mv16.x, mv16.y,                                                                          pCurrent, 2 * x, 2 * y,
200                                                             current->motion_flags, current->quant, current->fcode,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
201                                                         pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);                                                                          current->motion_flags,
202                                                                            current->quant, current->fcode, pParam,
203                                  pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                                          pMBs, prevMBs, &pMB->mvs[0],
204                                                         2 * j, 2 * i + 1, mv16.x, mv16.y,                                                                          &pMB->pmvs[0]);
205                                                             current->motion_flags, current->quant, current->fcode,                                          }
206                                                         pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);                                          if (sad8 < pMB->sad16) {
207    
208                                  pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                  predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
209                                                         2 * j + 1, 2 * i + 1, mv16.x, mv16.y,                                                  sad8 += pMB->sad8[1] =
210                                                             current->motion_flags, current->quant, current->fcode,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
211                                                         pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);                                                                          pCurrent, 2 * x + 1, 2 * y,
212                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
213                                  sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];                                                                          current->motion_flags,
214                                                                            current->quant, current->fcode, pParam,
215                                                                            pMBs, prevMBs, &pMB->mvs[1],
216                                                                            &pMB->pmvs[1]);
217                                            }
218                                            if (sad8 < pMB->sad16) {
219                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
220                                                    sad8 += pMB->sad8[2] =
221                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
222                                                                            pCurrent, 2 * x, 2 * y + 1,
223                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
224                                                                            current->motion_flags,
225                                                                            current->quant, current->fcode, pParam,
226                                                                            pMBs, prevMBs, &pMB->mvs[2],
227                                                                            &pMB->pmvs[2]);
228                                            }
229                                            if (sad8 < pMB->sad16) {
230                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
231                                                    sad8 += pMB->sad8[3] =
232                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
233                                                                            pCurrent, 2 * x + 1, 2 * y + 1,
234                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
235                                                                            current->motion_flags,
236                                                                            current->quant, current->fcode, pParam,
237                                                                            pMBs, prevMBs,
238                                                                            &pMB->mvs[3],
239                                                                            &pMB->pmvs[3]);
240                          }                          }
241    
   
242                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
243                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
244                          */                          */
245    
246                          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  
247                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
248                                                    pMB->sad8[0] *= 4;
249                                                    pMB->sad8[1] *= 4;
250                                                    pMB->sad8[2] *= 4;
251                                                    pMB->sad8[3] *= 4;
252                                                    continue;
253                          }                          }
254                          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;  
                         }  
255                  }                  }
256    
257  /*      dprintf("*** AFTER ***", pMBs[0].b_mvs[0].x);                          pMB->mode = MODE_INTER;
258          for (i = 0; i < iHcount; i++)                          pMB->pmvs[0] = pmv;     /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
259                  for (j = 0; j < iWcount; j++)                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
260                  {                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
261                          dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,                                  pMB->sad16;
262                                  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);  
263                  }                  }
         */  
264    
265          return 0;          return 0;
266  }  }
267    
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
   
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
268    
269  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
270    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
271      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
272    { \    { \
273      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \
274      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
     if (iSAD <= iQuant * 96)    \  
         iSAD -= MV16_00_BIAS; \  
275      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
276      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
277  }  }
278    
279  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
280      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
281      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
282      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
283      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
284  }  }
# Line 449  Line 288 
288      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
289    { \    { \
290      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
291      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
292      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
293      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
294  }  }
# Line 459  Line 298 
298      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
299    { \    { \
300      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
301      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
302      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
303      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
304  }  }
# Line 469  Line 308 
308      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
309    { \    { \
310      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
311      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
312      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
313      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
314  }  }
# Line 477  Line 316 
316    
317  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
318    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \
319    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\    iSAD += calc_delta_8(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
320    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
321    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
322  }  }
# Line 485  Line 324 
324  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
325    { \    { \
326      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
327      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
328      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
329      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
330  }  }
# Line 495  Line 334 
334      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
335    { \    { \
336      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
337      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
338      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
339      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
340  }  }
# Line 505  Line 344 
344      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
345    { \    { \
346      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
347      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
348      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
349      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
350  }  }
# Line 515  Line 354 
354      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
355    { \    { \
356      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
357      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
358      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
359      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
360  }  }
# Line 541  Line 380 
380          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
381          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
382          int32_t iSAD;          int32_t iSAD;
383          int32_t pred_x,pred_y;          VECTOR pred;
384    
385    
386          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
387    
388          iSAD = sad16( cur,          iSAD = sad16( cur,
389                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
# Line 553  Line 393 
393    
394          currMV->x = 0;          currMV->x = 0;
395          currMV->y = 0;          currMV->y = 0;
396          currPMV->x = -pred_x;          currPMV->x = -pred.x;
397          currPMV->y = -pred_y;          currPMV->y = -pred.y;
398    
399          return iSAD;          return iSAD;
400    
401  }  }
402  */  */
403    
404  int32_t Diamond16_MainSearch(  int32_t
405          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
406          const uint8_t * const pRefH,          const uint8_t * const pRefH,
407          const uint8_t * const pRefV,          const uint8_t * const pRefV,
408          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
409          const uint8_t * const cur,          const uint8_t * const cur,
410          const int x, const int y,                                           const int x,
411          int32_t startx, int32_t starty,                                           const int y,
412          int32_t iMinSAD,                                           const int start_x,
413                                             const int start_y,
414                                             int iMinSAD,
415          VECTOR * const currMV,          VECTOR * const currMV,
416          const VECTOR * const pmv,                                           const int center_x,
417          const int32_t min_dx, const int32_t max_dx,                                           const int center_y,
418          const int32_t min_dy, const int32_t max_dy,                                           const int32_t min_dx,
419                                             const int32_t max_dx,
420                                             const int32_t min_dy,
421                                             const int32_t max_dy,
422          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
423          const int32_t iDiamondSize,          const int32_t iDiamondSize,
424          const int32_t iFcode,          const int32_t iFcode,
# Line 583  Line 428 
428  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
429    
430          int32_t iDirection=0;          int32_t iDirection=0;
431            int32_t iDirectionBackup;
432          int32_t iSAD;          int32_t iSAD;
433          VECTOR backupMV;          VECTOR backupMV;
434          backupMV.x = startx;  
435          backupMV.y = starty;          backupMV.x = start_x;
436            backupMV.y = start_y;
437    
438  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
439    
# Line 595  Line 442 
442          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
443          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
444    
445          if (iDirection)          if (iDirection) {
446                  while (!iFound)                  while (!iFound) {
                 {  
447                          iFound = 1;                          iFound = 1;
448                          backupMV=*currMV;                          backupMV=*currMV;
449                            iDirectionBackup = iDirection;
450    
451                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
452                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
453                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
454                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
455                          if ( iDirection != 4)                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
456                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                     backupMV.y, 2);
457                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
458                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
459                                                                                       backupMV.y - iDiamondSize, 3);
460                            if (iDirectionBackup != 3)
461                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
462                                                                                       backupMV.y + iDiamondSize, 4);
463                  }                  }
464          else          } else {
465          {                  currMV->x = start_x;
466                  currMV->x = startx;                  currMV->y = start_y;
                 currMV->y = starty;  
467          }          }
468          return iMinSAD;          return iMinSAD;
469  }  }
470    
471  int32_t Square16_MainSearch(  int32_t
472                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
473                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
474                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
475                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
476                                          const uint8_t * const cur,                                          const uint8_t * const cur,
477                                          const int x, const int y,                                          const int x,
478                                          int32_t startx, int32_t starty,                                          const int y,
479                                          int32_t iMinSAD,                                          const int start_x,
480                                            const int start_y,
481                                            int iMinSAD,
482                                          VECTOR * const currMV,                                          VECTOR * const currMV,
483                                          const VECTOR * const pmv,                                          const int center_x,
484                                          const int32_t min_dx, const int32_t max_dx,                                          const int center_y,
485                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
486                                            const int32_t max_dx,
487                                            const int32_t min_dy,
488                                            const int32_t max_dy,
489                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
490                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
491                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 642  Line 497 
497          int32_t iDirection=0;          int32_t iDirection=0;
498          int32_t iSAD;          int32_t iSAD;
499          VECTOR backupMV;          VECTOR backupMV;
500          backupMV.x = startx;  
501          backupMV.y = starty;          backupMV.x = start_x;
502            backupMV.y = start_y;
503    
504  /* It's one search with full square pattern, and new parts for all following diamonds */  /* It's one search with full square pattern, and new parts for all following diamonds */
505    
# Line 658  Line 514 
514          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
515          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
516    
517          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
518          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
519          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
520          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
521            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
522                                                             backupMV.y - iDiamondSize, 7);
523            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
524                                                             backupMV.y + iDiamondSize, 8);
525    
526    
527          if (iDirection)          if (iDirection) {
528                  while (!iFound)                  while (!iFound) {
                 {  
529                          iFound = 1;                          iFound = 1;
530                          backupMV=*currMV;                          backupMV=*currMV;
531    
532                          switch (iDirection)                          switch (iDirection) {
                         {  
533                                  case 1:                                  case 1:
534                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
535                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
536                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
537                                                                                     backupMV.y - iDiamondSize, 5);
538                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
539                                                                                     backupMV.y - iDiamondSize, 7);
540                                          break;                                          break;
541                                  case 2:                                  case 2:
542                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
543                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
544                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
545                                                                                     backupMV.y + iDiamondSize, 6);
546                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
547                                                                                     backupMV.y + iDiamondSize, 8);
548                                          break;                                          break;
549    
550                                  case 3:                                  case 3:
551                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
552                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
553                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
554                                                                                     backupMV.y - iDiamondSize, 7);
555                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
556                                                                                     backupMV.y + iDiamondSize, 8);
557                                          break;                                          break;
558    
559                                  case 4:                                  case 4:
560                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
561                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
562                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
563                                                                                     backupMV.y - iDiamondSize, 5);
564                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
565                                                                                     backupMV.y + iDiamondSize, 6);
566                                          break;                                          break;
567    
568                                  case 5:                                  case 5:
569                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
570                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
571                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
572                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
573                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
574                                                                                     backupMV.y - iDiamondSize, 5);
575                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
576                                                                                     backupMV.y + iDiamondSize, 6);
577                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
578                                                                                     backupMV.y - iDiamondSize, 7);
579                                          break;                                          break;
580    
581                                  case 6:                                  case 6:
582                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
583                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
584                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
585                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
586                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
587                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
588                                                                                     backupMV.y - iDiamondSize, 5);
589                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
590                                                                                     backupMV.y + iDiamondSize, 6);
591                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
592                                                                                     backupMV.y + iDiamondSize, 8);
593    
594                                          break;                                          break;
595    
596                                  case 7:                                  case 7:
597                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
598                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
599                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
600                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
601                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
602                                                                                     backupMV.y - iDiamondSize, 5);
603                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
604                                                                                     backupMV.y - iDiamondSize, 7);
605                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
606                                                                                     backupMV.y + iDiamondSize, 8);
607                                          break;                                          break;
608    
609                                  case 8:                                  case 8:
610                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
611                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
612                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
613                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
614                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
615                                                                                     backupMV.y + iDiamondSize, 6);
616                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
617                                                                                     backupMV.y - iDiamondSize, 7);
618                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
619                                                                                     backupMV.y + iDiamondSize, 8);
620                                          break;                                          break;
621                          default:                          default:
622                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
623                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
624                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
625                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
626                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
627                                                                                     3);
628                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
629                                                                                     4);
630    
631                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
632                                                                                     backupMV.y - iDiamondSize, 5);
633                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
634                                                                                     backupMV.y + iDiamondSize, 6);
635                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
636                                                                                     backupMV.y - iDiamondSize, 7);
637                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
638                                                                                     backupMV.y + iDiamondSize, 8);
639                                    break;
640                            }
641                    }
642            } else {
643                    currMV->x = start_x;
644                    currMV->y = start_y;
645            }
646            return iMinSAD;
647    }
648    
649    
650    int32_t
651    Full16_MainSearch(const uint8_t * const pRef,
652                                      const uint8_t * const pRefH,
653                                      const uint8_t * const pRefV,
654                                      const uint8_t * const pRefHV,
655                                      const uint8_t * const cur,
656                                      const int x,
657                                      const int y,
658                                      const int start_x,
659                                      const int start_y,
660                                      int iMinSAD,
661                                      VECTOR * const currMV,
662                                      const int center_x,
663                                      const int center_y,
664                                      const int32_t min_dx,
665                                      const int32_t max_dx,
666                                      const int32_t min_dy,
667                                      const int32_t max_dy,
668                                      const int32_t iEdgedWidth,
669                                      const int32_t iDiamondSize,
670                                      const int32_t iFcode,
671                                      const int32_t iQuant,
672                                      int iFound)
673    {
674            int32_t iSAD;
675            int32_t dx, dy;
676            VECTOR backupMV;
677    
678            backupMV.x = start_x;
679            backupMV.y = start_y;
680    
681            for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
682                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
683                            NOCHECK_MV16_CANDIDATE(dx, dy);
684    
685            return iMinSAD;
686    }
687    
688    int32_t
689    AdvDiamond16_MainSearch(const uint8_t * const pRef,
690                                                    const uint8_t * const pRefH,
691                                                    const uint8_t * const pRefV,
692                                                    const uint8_t * const pRefHV,
693                                                    const uint8_t * const cur,
694                                                    const int x,
695                                                    const int y,
696                                                    const int start_xi,
697                                                    const int start_yi,
698                                                    int iMinSAD,
699                                                    VECTOR * const currMV,
700                                                    const int center_x,
701                                                    const int center_y,
702                                                    const int32_t min_dx,
703                                                    const int32_t max_dx,
704                                                    const int32_t min_dy,
705                                                    const int32_t max_dy,
706                                                    const int32_t iEdgedWidth,
707                                                    const int32_t iDiamondSize,
708                                                    const int32_t iFcode,
709                                                    const int32_t iQuant,
710                                                    int iDirection)
711    {
712    
713            int32_t iSAD;
714            int start_x = start_xi, start_y = start_yi;
715    
716    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
717    
718            if (iDirection) {
719                    CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
720                    CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
721                    CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
722                    CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
723            } else {
724                    int bDirection = 1 + 2 + 4 + 8;
725    
726                    do {
727                            iDirection = 0;
728                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
729                                    CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
730    
731                            if (bDirection & 2)
732                                    CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
733    
734                            if (bDirection & 4)
735                                    CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
736    
737                            if (bDirection & 8)
738                                    CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
739    
740                            /* now we're doing diagonal checks near our candidate */
741    
742                            if (iDirection)         //checking if anything found
743                            {
744                                    bDirection = iDirection;
745                                    iDirection = 0;
746                                    start_x = currMV->x;
747                                    start_y = currMV->y;
748                                    if (bDirection & 3)     //our candidate is left or right
749                                    {
750                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
751                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
752                                    } else                  // what remains here is up or down
753                                    {
754                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
755                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
756                                    }
757    
758                                    if (iDirection) {
759                                            bDirection += iDirection;
760                                            start_x = currMV->x;
761                                            start_y = currMV->y;
762                                    }
763                            } else                          //about to quit, eh? not so fast....
764                            {
765                                    switch (bDirection) {
766                                    case 2:
767                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
768                                                                                             start_y - iDiamondSize, 2 + 4);
769                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
770                                                                                             start_y + iDiamondSize, 2 + 8);
771                                            break;
772                                    case 1:
773    
774                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
775                                                                                             start_y - iDiamondSize, 1 + 4);
776                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
777                                                                                             start_y + iDiamondSize, 1 + 8);
778                                            break;
779                                    case 2 + 4:
780                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
781                                                                                             start_y - iDiamondSize, 1 + 4);
782                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
783                                                                                             start_y - iDiamondSize, 2 + 4);
784                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
785                                                                                             start_y + iDiamondSize, 2 + 8);
786                                            break;
787                                    case 4:
788                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
789                                                                                             start_y - iDiamondSize, 2 + 4);
790                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
791                                                                                             start_y - iDiamondSize, 1 + 4);
792                                            break;
793                                    case 8:
794                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
795                                                                                             start_y + iDiamondSize, 2 + 8);
796                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
797                                                                                             start_y + iDiamondSize, 1 + 8);
798                                            break;
799                                    case 1 + 4:
800                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
801                                                                                             start_y + iDiamondSize, 1 + 8);
802                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
803                                                                                             start_y - iDiamondSize, 1 + 4);
804                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
805                                                                                             start_y - iDiamondSize, 2 + 4);
806                                            break;
807                                    case 2 + 8:
808                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
809                                                                                             start_y - iDiamondSize, 1 + 4);
810                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
811                                                                                             start_y + iDiamondSize, 1 + 8);
812                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
813                                                                                             start_y + iDiamondSize, 2 + 8);
814                                            break;
815                                    case 1 + 8:
816                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
817                                                                                             start_y - iDiamondSize, 2 + 4);
818                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
819                                                                                             start_y + iDiamondSize, 2 + 8);
820                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
821                                                                                             start_y + iDiamondSize, 1 + 8);
822                                            break;
823                                    default:                //1+2+4+8 == we didn't find anything at all
824                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
825                                                                                             start_y - iDiamondSize, 1 + 4);
826                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
827                                                                                             start_y + iDiamondSize, 1 + 8);
828                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
829                                                                                             start_y - iDiamondSize, 2 + 4);
830                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
831                                                                                             start_y + iDiamondSize, 2 + 8);
832                                            break;
833                                    }
834                                    if (!iDirection)
835                                            break;          //ok, the end. really
836                                    else {
837                                            bDirection = iDirection;
838                                            start_x = currMV->x;
839                                            start_y = currMV->y;
840                                    }
841                            }
842                    }
843                    while (1);                              //forever
844            }
845            return iMinSAD;
846    }
847    
848    #define CHECK_MV16_F_INTERPOL(X,Y) { \
849      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
850        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
851      { \
852        iSAD = sad16bi( cur, \
853                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
854                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
855                            iEdgedWidth); \
856        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
857        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
858        if (iSAD < iMinSAD) \
859        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); } } \
860    }
861    
862    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y) { \
863      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
864        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
865      { \
866        iSAD = sad16bi( cur, \
867                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
868                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
869                            iEdgedWidth); \
870        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
871        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
872        if (iSAD < iMinSAD) \
873        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); iFound=0;} } \
874    }
875    
876    #define CHECK_MV16_B_INTERPOL(X,Y) { \
877      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
878        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
879      { \
880        iSAD = sad16bi( cur, \
881                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
882                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
883                            iEdgedWidth); \
884        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
885        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
886        if (iSAD < iMinSAD) \
887        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); } } \
888    }
889    
890    #define CHECK_MV16_B_INTERPOL_FOUND(X,Y) { \
891      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
892        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
893      { \
894        iSAD = sad16bi( cur, \
895                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
896                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
897                            iEdgedWidth); \
898        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
899        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
900        if (iSAD < iMinSAD) \
901        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); iFound=0;} } \
902    }
903    
904    int32_t
905    Diamond16_InterpolMainSearch(const uint8_t * const f_pRef,
906                                                             const uint8_t * const f_pRefH,
907                                                             const uint8_t * const f_pRefV,
908                                                             const uint8_t * const f_pRefHV,
909    
910                                                             const uint8_t * const cur,
911    
912                                                             const uint8_t * const b_pRef,
913                                                             const uint8_t * const b_pRefH,
914                                                             const uint8_t * const b_pRefV,
915                                                             const uint8_t * const b_pRefHV,
916    
917                                                             const int x,
918                                                             const int y,
919    
920                                                             const int f_start_x,
921                                                             const int f_start_y,
922                                                             const int b_start_x,
923                                                             const int b_start_y,
924    
925                                                             int iMinSAD,
926                                                             VECTOR * const f_currMV,
927                                                             VECTOR * const b_currMV,
928    
929                                                             const int f_center_x,
930                                                             const int f_center_y,
931                                                             const int b_center_x,
932                                                             const int b_center_y,
933    
934                                                             const int32_t f_min_dx,
935                                                             const int32_t f_max_dx,
936                                                             const int32_t f_min_dy,
937                                                             const int32_t f_max_dy,
938    
939                                                             const int32_t b_min_dx,
940                                                             const int32_t b_max_dx,
941                                                             const int32_t b_min_dy,
942                                                             const int32_t b_max_dy,
943    
944                                                             const int32_t iEdgedWidth,
945                                                             const int32_t iDiamondSize,
946    
947                                                             const int32_t f_iFcode,
948                                                             const int32_t b_iFcode,
949    
950                                                             const int32_t iQuant,
951                                                             int iFound)
952    {
953    /* Do a diamond search around given starting point, return SAD of best */
954    
955            int32_t iSAD;
956    
957            VECTOR f_backupMV;
958            VECTOR b_backupMV;
959    
960                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          f_currMV->x = f_start_x;
961                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);          f_currMV->y = f_start_y;
962                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          b_currMV->x = b_start_x;
963                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);          b_currMV->y = b_start_y;
964    
965            do
966            {
967                    iFound = 1;
968    
969                    f_backupMV = *f_currMV;
970    
971                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x - iDiamondSize, f_backupMV.y);
972                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x + iDiamondSize, f_backupMV.y);
973                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y - iDiamondSize);
974                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y + iDiamondSize);
975    
976                    b_backupMV = *b_currMV;
977    
978                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x - iDiamondSize, b_backupMV.y);
979                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x + iDiamondSize, b_backupMV.y);
980                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y - iDiamondSize);
981                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y + iDiamondSize);
982    
983            } while (!iFound);
984    
985            return iMinSAD;
986    }
987    
988    /* Sorry, these MACROS really got too large... I'll turn them into function soon! */
989    
990    #define CHECK_MV16_DIRECT_FOUND(X,Y) \
991            if ( (X)>=(-32) && (X)<=(31) && ((Y)>=-32) && ((Y)<=31) ) \
992            { int k;\
993            VECTOR mvs,b_mvs;       \
994            iSAD = 0;\
995            for (k = 0; k < 4; k++) {       \
996                                            mvs.x = (int32_t) ((TRB * directmv[k].x) / TRD + (X));          \
997                        b_mvs.x = (int32_t) (((X) == 0)                                                     \
998                                                                                    ? ((TRB - TRD) * directmv[k].x) / TRD   \
999                                                : mvs.x - directmv[k].x);                           \
1000                                                                                                                                                                    \
1001                        mvs.y = (int32_t) ((TRB * directmv[k].y) / TRD + (Y));              \
1002                            b_mvs.y = (int32_t) (((Y) == 0)                                                         \
1003                                                                                    ? ((TRB - TRD) * directmv[k].y) / TRD   \
1004                                                : mvs.y - directmv[k].y);                           \
1005                                                                                                                                                                    \
1006      if ( (mvs.x <= max_dx) && (mvs.x >= min_dx) \
1007        && (mvs.y <= max_dy) && (mvs.y >= min_dy)  \
1008            && (b_mvs.x <= max_dx) && (b_mvs.x >= min_dx)  \
1009        && (b_mvs.y <= max_dy) && (b_mvs.y >= min_dy) ) { \
1010                iSAD += sad8bi( cur + 8*(k&1) + 8*(k>>1)*iEdgedWidth,                                                                                                       \
1011                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1012                                            mvs.x, mvs.y, iEdgedWidth),                                                             \
1013                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1014                                            b_mvs.x, b_mvs.y, iEdgedWidth),                                                         \
1015                            iEdgedWidth); \
1016                    }       \
1017            else    \
1018                    iSAD = 65535;   \
1019            } \
1020            iSAD += calc_delta_16((X),(Y), 1, iQuant);\
1021            if (iSAD < iMinSAD) \
1022                {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iFound=0; } \
1023    }
1024    
1025    
1026    
1027    int32_t
1028    Diamond16_DirectMainSearch(
1029                                            const uint8_t * const f_pRef,
1030                                            const uint8_t * const f_pRefH,
1031                                            const uint8_t * const f_pRefV,
1032                                            const uint8_t * const f_pRefHV,
1033    
1034                                            const uint8_t * const cur,
1035    
1036                                            const uint8_t * const b_pRef,
1037                                            const uint8_t * const b_pRefH,
1038                                            const uint8_t * const b_pRefV,
1039                                            const uint8_t * const b_pRefHV,
1040    
1041                                            const int x,
1042                                            const int y,
1043    
1044                                            const int TRB,
1045                                            const int TRD,
1046    
1047                                        const int start_x,
1048                                        const int start_y,
1049    
1050                                        int iMinSAD,
1051                                        VECTOR * const currMV,
1052                                            const VECTOR * const directmv,
1053    
1054                                        const int32_t min_dx,
1055                                            const int32_t max_dx,
1056                                            const int32_t min_dy,
1057                                            const int32_t max_dy,
1058    
1059                                            const int32_t iEdgedWidth,
1060                                            const int32_t iDiamondSize,
1061    
1062                                            const int32_t iQuant,
1063                                            int iFound)
1064    {
1065    /* Do a diamond search around given starting point, return SAD of best */
1066    
1067            int32_t iSAD;
1068    
1069            VECTOR backupMV;
1070    
1071            currMV->x = start_x;
1072            currMV->y = start_y;
1073    
1074    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1075    
1076            do
1077            {
1078                    iFound = 1;
1079    
1080                    backupMV = *currMV;
1081    
1082                    CHECK_MV16_DIRECT_FOUND(backupMV.x - iDiamondSize, backupMV.y);
1083                    CHECK_MV16_DIRECT_FOUND(backupMV.x + iDiamondSize, backupMV.y);
1084                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y - iDiamondSize);
1085                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y + iDiamondSize);
1086    
1087            } while (!iFound);
1088    
1089            return iMinSAD;
1090    }
1091    
1092    
1093    int32_t
1094    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1095                                               const uint8_t * const pRefH,
1096                                               const uint8_t * const pRefV,
1097                                               const uint8_t * const pRefHV,
1098                                               const uint8_t * const cur,
1099                                               const int x,
1100                                               const int y,
1101                                               const int start_xi,
1102                                               const int start_yi,
1103                                               int iMinSAD,
1104                                               VECTOR * const currMV,
1105                                               const int center_x,
1106                                               const int center_y,
1107                                               const int32_t min_dx,
1108                                               const int32_t max_dx,
1109                                               const int32_t min_dy,
1110                                               const int32_t max_dy,
1111                                               const int32_t iEdgedWidth,
1112                                               const int32_t iDiamondSize,
1113                                               const int32_t iFcode,
1114                                               const int32_t iQuant,
1115                                               int iDirection)
1116    {
1117    
1118            int32_t iSAD;
1119            int start_x = start_xi, start_y = start_yi;
1120    
1121    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1122    
1123            if (iDirection) {
1124                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1125                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1126                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1127                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1128            } else {
1129                    int bDirection = 1 + 2 + 4 + 8;
1130    
1131                    do {
1132                            iDirection = 0;
1133                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
1134                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1135    
1136                            if (bDirection & 2)
1137                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1138    
1139                            if (bDirection & 4)
1140                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1141    
1142                            if (bDirection & 8)
1143                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1144    
1145                            /* now we're doing diagonal checks near our candidate */
1146    
1147                            if (iDirection)         //checking if anything found
1148                            {
1149                                    bDirection = iDirection;
1150                                    iDirection = 0;
1151                                    start_x = currMV->x;
1152                                    start_y = currMV->y;
1153                                    if (bDirection & 3)     //our candidate is left or right
1154                                    {
1155                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1156                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1157                                    } else                  // what remains here is up or down
1158                                    {
1159                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1160                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1161                                    }
1162    
1163                                    if (iDirection) {
1164                                            bDirection += iDirection;
1165                                            start_x = currMV->x;
1166                                            start_y = currMV->y;
1167                                    }
1168                            } else                          //about to quit, eh? not so fast....
1169                            {
1170                                    switch (bDirection) {
1171                                    case 2:
1172                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1173                                                                                            start_y - iDiamondSize, 2 + 4);
1174                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1175                                                                                            start_y + iDiamondSize, 2 + 8);
1176                                            break;
1177                                    case 1:
1178                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1179                                                                                            start_y - iDiamondSize, 1 + 4);
1180                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1181                                                                                            start_y + iDiamondSize, 1 + 8);
1182                                            break;
1183                                    case 2 + 4:
1184                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1185                                                                                            start_y - iDiamondSize, 1 + 4);
1186                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1187                                                                                            start_y - iDiamondSize, 2 + 4);
1188                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1189                                                                                            start_y + iDiamondSize, 2 + 8);
1190                                            break;
1191                                    case 4:
1192                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1193                                                                                            start_y - iDiamondSize, 2 + 4);
1194                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1195                                                                                            start_y - iDiamondSize, 1 + 4);
1196                                            break;
1197                                    case 8:
1198                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1199                                                                                            start_y + iDiamondSize, 2 + 8);
1200                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1201                                                                                            start_y + iDiamondSize, 1 + 8);
1202                                          break;                                          break;
1203                                    case 1 + 4:
1204                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1205                                                                                            start_y + iDiamondSize, 1 + 8);
1206                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1207                                                                                            start_y - iDiamondSize, 1 + 4);
1208                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1209                                                                                            start_y - iDiamondSize, 2 + 4);
1210                                            break;
1211                                    case 2 + 8:
1212                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1213                                                                                            start_y - iDiamondSize, 1 + 4);
1214                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1215                                                                                            start_y + iDiamondSize, 1 + 8);
1216                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1217                                                                                            start_y + iDiamondSize, 2 + 8);
1218                                            break;
1219                                    case 1 + 8:
1220                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1221                                                                                            start_y - iDiamondSize, 2 + 4);
1222                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1223                                                                                            start_y + iDiamondSize, 2 + 8);
1224                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1225                                                                                            start_y + iDiamondSize, 1 + 8);
1226                                            break;
1227                                    default:                //1+2+4+8 == we didn't find anything at all
1228                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1229                                                                                            start_y - iDiamondSize, 1 + 4);
1230                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1231                                                                                            start_y + iDiamondSize, 1 + 8);
1232                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1233                                                                                            start_y - iDiamondSize, 2 + 4);
1234                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1235                                                                                            start_y + iDiamondSize, 2 + 8);
1236                                            break;
1237                                    }
1238                                    if (!(iDirection))
1239                                            break;          //ok, the end. really
1240                                    else {
1241                                            bDirection = iDirection;
1242                                            start_x = currMV->x;
1243                                            start_y = currMV->y;
1244                                    }
1245                          }                          }
1246                  }                  }
1247          else                  while (1);                              //forever
                 {  
                         currMV->x = startx;  
                         currMV->y = starty;  
1248                  }                  }
1249          return iMinSAD;          return iMinSAD;
1250  }  }
1251    
1252    
1253  int32_t Full16_MainSearch(  int32_t
1254                                          const uint8_t * const pRef,  Full8_MainSearch(const uint8_t * const pRef,
1255                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1256                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1257                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1258                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1259                                          const int x, const int y,                                   const int x,
1260                                          int32_t startx, int32_t starty,                                   const int y,
1261                                          int32_t iMinSAD,                             const int start_x,
1262                               const int start_y,
1263                               int iMinSAD,
1264                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1265                                          const VECTOR * const pmv,                             const int center_x,
1266                                          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1267                                          const int32_t min_dy, const int32_t max_dy,                                   const int32_t min_dx,
1268                                     const int32_t max_dx,
1269                                     const int32_t min_dy,
1270                                     const int32_t max_dy,
1271                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
1272                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
1273                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 772  Line 1277 
1277          int32_t iSAD;          int32_t iSAD;
1278          int32_t dx,dy;          int32_t dx,dy;
1279          VECTOR backupMV;          VECTOR backupMV;
         backupMV.x = startx;  
         backupMV.y = starty;  
   
         for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)  
                 for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)  
                         NOCHECK_MV16_CANDIDATE(dx,dy);  
   
         return iMinSAD;  
 }  
1280    
1281  int32_t Full8_MainSearch(          backupMV.x = start_x;
1282                                          const uint8_t * const pRef,          backupMV.y = start_y;
                                         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)  
 {  
         int32_t iSAD;  
         int32_t dx,dy;  
         VECTOR backupMV;  
         backupMV.x = startx;  
         backupMV.y = starty;  
1283    
1284          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
1285                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 814  Line 1288 
1288          return iMinSAD;          return iMinSAD;
1289  }  }
1290    
1291    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1292    
1293    int32_t
1294  int32_t Halfpel16_Refine(  Halfpel16_Refine(const uint8_t * const pRef,
         const uint8_t * const pRef,  
1295          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1296          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1297          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1298          const uint8_t * const cur,          const uint8_t * const cur,
1299          const int x, const int y,                                   const int x,
1300                                     const int y,
1301          VECTOR * const currMV,          VECTOR * const currMV,
1302          int32_t iMinSAD,          int32_t iMinSAD,
1303          const VECTOR * const pmv,                             const int center_x,
1304          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1305          const int32_t min_dy, const int32_t max_dy,                                   const int32_t min_dx,
1306                                     const int32_t max_dx,
1307                                     const int32_t min_dy,
1308                                     const int32_t max_dy,
1309          const int32_t iFcode,          const int32_t iFcode,
1310          const int32_t iQuant,          const int32_t iQuant,
1311          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 852  Line 1330 
1330  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1331    
1332    
1333  int32_t PMVfastSearch16(  
1334                                          const uint8_t * const pRef,  int32_t
1335    PMVfastSearch16(const uint8_t * const pRef,
1336                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1337                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1338                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1339                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1340                                          const int x, const int y,                                  const int x,
1341                                    const int y,
1342                                    const int start_x,      /* start is searched first, so it should contain the most */
1343                                    const int start_y,  /* likely motion vector for this block */
1344                                    const int center_x,     /* center is from where length of MVs is measured */
1345                                    const int center_y,
1346                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1347                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1348                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 890  Line 1374 
1374          VECTOR pmv[4];          VECTOR pmv[4];
1375          int32_t psad[4];          int32_t psad[4];
1376    
1377          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1378    
1379          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1380    
1381          static int32_t threshA,threshB;          int32_t threshA, threshB;
1382          int32_t bPredEq;          int32_t bPredEq;
1383          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1384    
1385  /* Get maximum range */  /* Get maximum range */
1386          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1387                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1388    
1389  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1390    
1391          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1392          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1393          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1394          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1395          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1396          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1397    
1398          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1399            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1400    
1401          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1402                  threshA =  512;                  threshA =  512;
1403                  threshB = 1024;                  threshB = 1024;
1404            } else {
         }  
         else  
         {  
1405                  threshA = psad[0];                  threshA = psad[0];
1406                  threshB = threshA+256;                  threshB = threshA+256;
1407                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1408                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1409                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1410                            threshA = 1024;
1411                    if (threshB > 1792)
1412                            threshB = 1792;
1413          }          }
1414    
1415          iFound=0;          iFound=0;
1416    
 /* 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;  
   
1417  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1418     MinSAD=SAD     MinSAD=SAD
1419     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 957  Line 1421 
1421     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1422  */  */
1423    
1424            currMV->x = start_x;
1425            currMV->y = start_y;
1426    
1427  // 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! */  
1428                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1429                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1430          }          }
1431    
1432          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1433                  currMV->x=max_dx;                  currMV->x=max_dx;
1434          }          }
1435          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1436                  currMV->x=min_dx;                  currMV->x=min_dx;
1437          }          }
1438          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1439                  currMV->y=max_dy;                  currMV->y=max_dy;
1440          }          }
1441          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1442                  currMV->y=min_dy;                  currMV->y=min_dy;
1443          }          }
1444    
1445          iMinSAD = sad16( cur,          iMinSAD =
1446                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1447                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1448          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1449            iMinSAD +=
1450          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1451          {                                            (uint8_t) iFcode, iQuant);
1452    
1453            if ((iMinSAD < 256) ||
1454                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1455                     ((int32_t) iMinSAD < prevMB->sad16))) {
1456                    if (iMinSAD < (int)(2 * iQuant))        // high chances for SKIP-mode
1457                    {
1458                            if (!MVzero(*currMV)) {
1459                                    iMinSAD += MV16_00_BIAS;
1460                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1461                                    iMinSAD -= MV16_00_BIAS;
1462                            }
1463                    }
1464    
1465                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1466                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 998  Line 1468 
1468                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
1469          }          }
1470    
1471    
1472    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1473       vector of the median.
1474       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1475    */
1476    
1477            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1478                    iFound = 2;
1479    
1480    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1481       Otherwise select large Diamond Search.
1482    */
1483    
1484            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1485                    iDiamondSize = 1;               // halfpel!
1486            else
1487                    iDiamondSize = 2;               // halfpel!
1488    
1489            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1490                    iDiamondSize *= 2;
1491    
1492  /*  /*
1493     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.
1494     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1495     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1496     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1497  */  */
1498    
1499  // (0,0) is always possible  // (0,0) is always possible
1500    
1501            if (!MVzero(pmv[0]))
1502          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1503    
1504  // previous frame MV is always possible  // previous frame MV is always possible
1505    
1506            if (!MVzero(prevMB->mvs[0]))
1507                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1508          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1509    
1510  // left neighbour, if allowed  // left neighbour, if allowed
1511          if (x != 0)  
1512          {          if (!MVzero(pmv[1]))
1513                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1514                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1515                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1516                                            pmv[1].x = EVEN(pmv[1].x);
1517                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1518                  }                  }
1519    
1520                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1521          }          }
   
1522  // top neighbour, if allowed  // top neighbour, if allowed
1523          if (y != 0)          if (!MVzero(pmv[2]))
1524          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1525                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1526                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1527                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1528                                                    pmv[2].x = EVEN(pmv[2].x);
1529                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1530                  }                  }
1531                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1532    
1533  // top right neighbour, if allowed  // top right neighbour, if allowed
1534                  if ((uint32_t)x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1535                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1536                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1537                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1538                                                                            if (!MVequal(pmv[3], pmv[2])) {
1539                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1540                                                                                            pmv[3].x = EVEN(pmv[3].x);
1541                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1542                          }                          }
1543                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1544                                                                                                                             pmv[3].y);
1545                  }                  }
1546          }          }
1547    
1548            if ((MVzero(*currMV)) &&
1549                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1550                    iMinSAD -= MV16_00_BIAS;
1551    
1552    
1553  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1554     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.
1555  */  */
1556    
1557          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1558          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1559                     ((int32_t) iMinSAD < prevMB->sad16))) {
1560                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1561                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1562                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1065  Line 1574 
1574     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1575  */  */
1576    
1577            if (MotionFlags & PMV_USESQUARES16)
1578                    MainSearchPtr = Square16_MainSearch;
1579            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1580                    MainSearchPtr = AdvDiamond16_MainSearch;
1581            else
1582                    MainSearchPtr = Diamond16_MainSearch;
1583    
1584          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1585    
1586    
1587  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1588          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1589                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1590                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1591                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1592                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1593                                                      iQuant, iFound);
1594    
1595          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1596                  *currMV = newMV;                  *currMV = newMV;
1597                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1598          }          }
1599    
1600          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1601  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1602    
1603                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1604                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1605                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1606                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1607                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1608                                                                      iDiamondSize, iFcode, iQuant, iFound);
1609    
1610                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1611                          *currMV = newMV;                          *currMV = newMV;
1612                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1613                  }                  }
1614                  }                  }
1615    
1616                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1617                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1618                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1619                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1620                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1621                                                                      iEdgedWidth, iDiamondSize, iFcode,
1622                                                                      iQuant, iFound);
1623    
1624                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1625                          *currMV = newMV;                          *currMV = newMV;
1626                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1627                  }                  }
# Line 1116  Line 1634 
1634    
1635  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1636          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1637                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1638                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1639                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1640                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1641    
1642  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1643          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1644          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1645          return iMinSAD;          return iMinSAD;
1646  }  }
1647    
# Line 1132  Line 1650 
1650    
1651    
1652    
1653  int32_t Diamond8_MainSearch(  int32_t
1654          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1655          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1656          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1657          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1658          const uint8_t * const cur,          const uint8_t * const cur,
1659          const int x, const int y,                                          const int x,
1660          int32_t startx, int32_t starty,                                          const int y,
1661                                            const int32_t start_x,
1662                                            const int32_t start_y,
1663          int32_t iMinSAD,          int32_t iMinSAD,
1664          VECTOR * const currMV,          VECTOR * const currMV,
1665          const VECTOR * const pmv,                                          const int center_x,
1666          const int32_t min_dx, const int32_t max_dx,                                          const int center_y,
1667          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1668                                            const int32_t max_dx,
1669                                            const int32_t min_dy,
1670                                            const int32_t max_dy,
1671          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1672          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1673          const int32_t iFcode,          const int32_t iFcode,
# Line 1154  Line 1677 
1677  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1678    
1679          int32_t iDirection=0;          int32_t iDirection=0;
1680            int32_t iDirectionBackup;
1681          int32_t iSAD;          int32_t iSAD;
1682          VECTOR backupMV;          VECTOR backupMV;
1683          backupMV.x = startx;  
1684          backupMV.y = starty;          backupMV.x = start_x;
1685            backupMV.y = start_y;
1686    
1687  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1688    
# Line 1166  Line 1691 
1691          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1692          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1693    
1694          if (iDirection)          if (iDirection) {
1695                  while (!iFound)                  while (!iFound) {
                 {  
1696                          iFound = 1;                          iFound = 1;
1697                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1698                            iDirectionBackup = iDirection;
1699    
1700                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1701                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1702                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1703                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1704                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1705                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1706                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1707                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1708                                                                                      backupMV.y - iDiamondSize, 3);
1709                            if (iDirectionBackup != 3)
1710                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1711                                                                                      backupMV.y + iDiamondSize, 4);
1712                  }                  }
1713          else          } else {
1714                    currMV->x = start_x;
1715                    currMV->y = start_y;
1716            }
1717            return iMinSAD;
1718    }
1719    
1720    
1721    
1722    
1723    int32_t
1724    Square8_MainSearch(const uint8_t * const pRef,
1725                                       const uint8_t * const pRefH,
1726                                       const uint8_t * const pRefV,
1727                                       const uint8_t * const pRefHV,
1728                                       const uint8_t * const cur,
1729                                       const int x,
1730                                       const int y,
1731                                       const int32_t start_x,
1732                                       const int32_t start_y,
1733                                       int32_t iMinSAD,
1734                                       VECTOR * const currMV,
1735                                       const int center_x,
1736                                       const int center_y,
1737                                       const int32_t min_dx,
1738                                       const int32_t max_dx,
1739                                       const int32_t min_dy,
1740                                       const int32_t max_dy,
1741                                       const int32_t iEdgedWidth,
1742                                       const int32_t iDiamondSize,
1743                                       const int32_t iFcode,
1744                                       const int32_t iQuant,
1745                                       int iFound)
1746          {          {
1747                  currMV->x = startx;  /* Do a square search around given starting point, return SAD of best */
1748                  currMV->y = starty;  
1749            int32_t iDirection = 0;
1750            int32_t iSAD;
1751            VECTOR backupMV;
1752    
1753            backupMV.x = start_x;
1754            backupMV.y = start_y;
1755    
1756    /* It's one search with full square pattern, and new parts for all following diamonds */
1757    
1758    /*   new direction are extra, so 1-4 is normal diamond
1759          537
1760          1*2
1761          648
1762    */
1763    
1764            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1765            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1766            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1767            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1768    
1769            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1770                                                             backupMV.y - iDiamondSize, 5);
1771            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1772                                                             backupMV.y + iDiamondSize, 6);
1773            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1774                                                             backupMV.y - iDiamondSize, 7);
1775            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1776                                                             backupMV.y + iDiamondSize, 8);
1777    
1778    
1779            if (iDirection) {
1780                    while (!iFound) {
1781                            iFound = 1;
1782                            backupMV = *currMV;
1783    
1784                            switch (iDirection) {
1785                            case 1:
1786                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1787                                                                                       backupMV.y, 1);
1788                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1789                                                                                     backupMV.y - iDiamondSize, 5);
1790                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1791                                                                                     backupMV.y - iDiamondSize, 7);
1792                                    break;
1793                            case 2:
1794                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1795                                                                                     2);
1796                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1797                                                                                     backupMV.y + iDiamondSize, 6);
1798                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1799                                                                                     backupMV.y + iDiamondSize, 8);
1800                                    break;
1801    
1802                            case 3:
1803                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1804                                                                                     4);
1805                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1806                                                                                     backupMV.y - iDiamondSize, 7);
1807                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1808                                                                                     backupMV.y + iDiamondSize, 8);
1809                                    break;
1810    
1811                            case 4:
1812                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1813                                                                                     3);
1814                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1815                                                                                     backupMV.y - iDiamondSize, 5);
1816                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1817                                                                                     backupMV.y + iDiamondSize, 6);
1818                                    break;
1819    
1820                            case 5:
1821                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1822                                                                                     1);
1823                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1824                                                                                     3);
1825                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1826                                                                                     backupMV.y - iDiamondSize, 5);
1827                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1828                                                                                     backupMV.y + iDiamondSize, 6);
1829                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1830                                                                                     backupMV.y - iDiamondSize, 7);
1831                                    break;
1832    
1833                            case 6:
1834                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1835                                                                                     2);
1836                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1837                                                                                     3);
1838    
1839                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1840                                                                                     backupMV.y - iDiamondSize, 5);
1841                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1842                                                                                     backupMV.y + iDiamondSize, 6);
1843                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1844                                                                                     backupMV.y + iDiamondSize, 8);
1845    
1846                                    break;
1847    
1848                            case 7:
1849                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1850                                                                                       backupMV.y, 1);
1851                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1852                                                                                     4);
1853                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1854                                                                                     backupMV.y - iDiamondSize, 5);
1855                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1856                                                                                     backupMV.y - iDiamondSize, 7);
1857                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1858                                                                                     backupMV.y + iDiamondSize, 8);
1859                                    break;
1860    
1861                            case 8:
1862                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1863                                                                                     2);
1864                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1865                                                                                     4);
1866                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1867                                                                                     backupMV.y + iDiamondSize, 6);
1868                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1869                                                                                     backupMV.y - iDiamondSize, 7);
1870                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1871                                                                                     backupMV.y + iDiamondSize, 8);
1872                                    break;
1873                            default:
1874                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1875                                                                                     1);
1876                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1877                                                                                     2);
1878                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1879                                                                                     3);
1880                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1881                                                                                     4);
1882    
1883                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1884                                                                                     backupMV.y - iDiamondSize, 5);
1885                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1886                                                                                     backupMV.y + iDiamondSize, 6);
1887                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1888                                                                                     backupMV.y - iDiamondSize, 7);
1889                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1890                                                                                     backupMV.y + iDiamondSize, 8);
1891                                    break;
1892                            }
1893                    }
1894            } else {
1895                    currMV->x = start_x;
1896                    currMV->y = start_y;
1897          }          }
1898          return iMinSAD;          return iMinSAD;
1899  }  }
1900    
1901  int32_t Halfpel8_Refine(  
1902          const uint8_t * const pRef,  
1903    
1904    
1905    int32_t
1906    Halfpel8_Refine_c(const uint8_t * const pRef,
1907          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1908          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1909          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1910          const uint8_t * const cur,          const uint8_t * const cur,
1911          const int x, const int y,                                    const int x,
1912                                      const int y,
1913          VECTOR * const currMV,          VECTOR * const currMV,
1914          int32_t iMinSAD,          int32_t iMinSAD,
1915          const VECTOR * const pmv,                                    const int center_x,
1916          const int32_t min_dx, const int32_t max_dx,                                    const int center_y,
1917          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
1918                                      const int32_t max_dx,
1919                                      const int32_t min_dy,
1920                                      const int32_t max_dy,
1921          const int32_t iFcode,          const int32_t iFcode,
1922          const int32_t iQuant,          const int32_t iQuant,
1923          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1225  Line 1942 
1942    
1943  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1944    
1945  int32_t PMVfastSearch8(  int32_t
1946                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1947                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1948                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1949                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1950                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1951                                          const int x, const int y,                             const int x,
1952                                          const int start_x, const int start_y,                             const int y,
1953                               const int start_x,
1954                               const int start_y,
1955                                    const int center_x,
1956                                    const int center_y,
1957                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1958                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1959                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1260  Line 1981 
1981          int32_t psad[4];          int32_t psad[4];
1982          VECTOR newMV;          VECTOR newMV;
1983          VECTOR backupMV;          VECTOR backupMV;
1984            VECTOR startMV;
1985    
1986          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1987          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1988    
1989          static int32_t threshA,threshB;           int32_t threshA, threshB;
1990          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1991          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1992    
1993          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1994    
1995  /* Get maximum range */          MainSearch8FuncPtr MainSearchPtr;
         get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                   x, y, 8, iWidth, iHeight, iFcode);  
1996    
1997  /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */          /* Init variables */
1998            startMV.x = start_x;
1999            startMV.y = start_y;
2000    
2001          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          /* Get maximum range */
2002          { min_dx = EVEN(min_dx);          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2003                              iFcode);
2004    
2005            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
2006                    min_dx = EVEN(min_dx);
2007          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
2008          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
2009          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
2010          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
2011    
2012          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
2013            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
2014    
2015          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2016                  threshA =  512/4;                  threshA =  512/4;
2017                  threshB = 1024/4;                  threshB = 1024/4;
2018    
2019          }          } else {
2020          else                  threshA = psad[0] / 4;  /* good estimate? */
         {  
                 threshA = psad[0]/4;                    /* good estimate */  
2021                  threshB = threshA+256/4;                  threshB = threshA+256/4;
2022                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
2023                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
2024                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
2025                            threshA = 1024 / 4;
2026                    if (threshB > 1792 / 4)
2027                            threshB = 1792 / 4;
2028          }          }
2029    
2030          iFound=0;          iFound=0;
2031    
 /* 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;  
   
2032  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2033     MinSAD=SAD     MinSAD=SAD
2034     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 1333  Line 2039 
2039    
2040  // Prepare for main loop  // Prepare for main loop
2041    
2042          currMV->x=start_x;              /* start with mv16 */    if (MotionFlags & PMV_USESQUARES8)
2043          currMV->y=start_y;        MainSearchPtr = Square8_MainSearch;
2044      else
2045    
2046            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2047                    MainSearchPtr = AdvDiamond8_MainSearch;
2048            else
2049                    MainSearchPtr = Diamond8_MainSearch;
2050    
         iMinSAD = sad8( cur,  
                         get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),  
                         iEdgedWidth);  
         iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;  
2051    
2052          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          *currMV = startMV;
2053          {  
2054            iMinSAD =
2055                    sad8(cur,
2056                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2057                                                    iEdgedWidth), iEdgedWidth);
2058            iMinSAD +=
2059                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2060                                             (uint8_t) iFcode, iQuant);
2061    
2062            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
2063                                                                    && ((int32_t) iMinSAD <
2064                                                                            prevMB->sad8[iSubBlock]))) {
2065                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2066                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2067                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
2068                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
2069          }          }
2070    
2071    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2072       vector of the median.
2073       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2074    */
2075    
2076            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
2077                    iFound = 2;
2078    
2079    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2080       Otherwise select large Diamond Search.
2081    */
2082    
2083            if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
2084                    iDiamondSize = 1;               // 1 halfpel!
2085            else
2086                    iDiamondSize = 2;               // 2 halfpel = 1 full pixel!
2087    
2088            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2089                    iDiamondSize *= 2;
2090    
2091    
2092  /*  /*
2093     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.
2094     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
2095     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
2096     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
2097  */  */
2098    
2099  // 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);  
2100    
2101  // (0,0) is always possible          if (!MVequal(pmv[0], startMV))
2102                    CHECK_MV8_CANDIDATE(center_x, center_y);
2103    
2104    // (0,0) if needed
2105            if (!MVzero(pmv[0]))
2106                    if (!MVzero(startMV))
2107          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2108    
2109  // previous frame MV is always possible  // previous frame MV if needed
2110          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
2111                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
2112                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
2113                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
2114                                                                            prevMB->mvs[iSubBlock].y);
2115    
2116            if ((iMinSAD <= threshA) ||
2117                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2118                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2119                    if (MotionFlags & PMV_QUICKSTOP16)
2120                            goto PMVfast8_Terminate_without_Refine;
2121                    if (MotionFlags & PMV_EARLYSTOP16)
2122                            goto PMVfast8_Terminate_with_Refine;
2123            }
2124    
2125  // left neighbour, if allowed  // left neighbour, if allowed and needed
2126          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
2127          {                  if (!MVequal(pmv[1], startMV))
2128                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
2129                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
2130                                            if (!(MotionFlags & PMV_HALFPEL8)) {
2131                                                    pmv[1].x = EVEN(pmv[1].x);
2132                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
2133                  }                  }
2134                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2135          }          }
2136    // top neighbour, if allowed and needed
2137  // top neighbour, if allowed          if (!MVzero(pmv[2]))
2138          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
2139          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
2140                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
2141                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
2142                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
2143                                                            pmv[2].x = EVEN(pmv[2].x);
2144                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
2145                  }                  }
2146                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2147    
2148  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
2149                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
2150                  {                                                          if (!MVequal(pmv[3], startMV))
2151                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
2152                          {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
2153                                                                                    if (!MVequal(pmv[3], pmv[1]))
2154                                                                                            if (!MVequal(pmv[3], pmv[2])) {
2155                                                                                                    if (!
2156                                                                                                            (MotionFlags &
2157                                                                                                             PMV_HALFPEL8)) {
2158                                                                                                            pmv[3].x = EVEN(pmv[3].x);
2159                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
2160                          }                          }
2161                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
2162                                                                                                                                            pmv[3].y);
2163                  }                  }
2164          }          }
2165    
2166            if ((MVzero(*currMV)) &&
2167                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2168                    iMinSAD -= MV8_00_BIAS;
2169    
2170    
2171  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
2172     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.
2173  */  */
2174    
2175          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2176          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2177                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2178                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2179                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2180                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1421  Line 2194 
2194          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2195    
2196  /* 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 */
2197          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2198                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2199                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2200                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2201                                                      iQuant, iFound);
2202    
2203          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2204                  *currMV = newMV;                  *currMV = newMV;
2205                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2206          }          }
2207    
2208          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2209  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
2210    
2211                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2212                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2213                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2214                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2215                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2216                                                                      iDiamondSize, iFcode, iQuant, iFound);
2217    
2218                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2219                          *currMV = newMV;                          *currMV = newMV;
2220                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2221                  }                  }
2222                  }                  }
2223    
2224                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2225                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2226                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2227                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2228                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2229                                                                      iQuant, iFound);
2230    
2231                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2232                          *currMV = newMV;                          *currMV = newMV;
2233                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2234                  }                  }
# Line 1469  Line 2241 
2241    
2242  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
2243          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2244                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2245                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2246                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2247                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2248    
2249    
2250  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
2251          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2252          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2253    
2254          return iMinSAD;          return iMinSAD;
2255  }  }
2256    
2257  int32_t EPZSSearch16(  int32_t
2258                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2259                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2260                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2261                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2262                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2263                                          const int x, const int y,                           const int x,
2264                             const int y,
2265                            const int start_x,
2266                            const int start_y,
2267                            const int center_x,
2268                            const int center_y,
2269                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2270                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2271                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1519  Line 2296 
2296          int32_t psad[8];          int32_t psad[8];
2297    
2298          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2299          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
2300    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2301          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
2302          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
2303    
2304          static int32_t thresh2;           int32_t thresh2;
2305          int32_t bPredEq;          int32_t bPredEq;
2306          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2307    
2308          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2309    
2310          if (oldMBs == NULL)          if (oldMBs == NULL) {
2311          {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2312                  fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2313          }          }
2314          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2315    
2316  /* Get maximum range */  /* Get maximum range */
2317          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,
2318                          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 */  
2319    
2320          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
2321          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2322            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2323            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2324            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2325          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2326            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2327          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2328    
2329  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2330          MinSAD=SAD          MinSAD=SAD
# Line 1559  Line 2335 
2335    
2336  // Prepare for main loop  // Prepare for main loop
2337    
2338          *currMV=pmv[0];         /* current best := median prediction */          currMV->x = start_x;
2339          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2340          {  
2341            if (!(MotionFlags & PMV_HALFPEL16)) {
2342                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2343                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2344          }          }
# Line 1577  Line 2354 
2354    
2355  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2356    
2357          iMinSAD = sad16( cur,          iMinSAD =
2358                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2359                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2360          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2361            iMinSAD +=
2362                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2363                                              (uint8_t) iFcode, iQuant);
2364    
2365  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2366          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD < 256) ||
2367                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2368                     ((int32_t) iMinSAD < prevMB->sad16))) {
2369                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2370                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2371                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1594  Line 2375 
2375  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2376    
2377  // previous frame MV  // previous frame MV
2378          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
2379    
2380  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2381  // 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
2382    
2383          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2384                  thresh2 =  512;                  thresh2 =  512;
2385          }          } else {
         else  
         {  
2386  /* 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] */
2387    
2388                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1616  Line 2394 
2394    
2395    
2396  // left neighbour, if allowed  // left neighbour, if allowed
2397          if (x != 0)          if (x != 0) {
2398          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2399                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2400                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2401                  }                  }
2402                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2403          }          }
   
2404  // top neighbour, if allowed  // top neighbour, if allowed
2405          if (y != 0)          if (y != 0) {
2406          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2407                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2408                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2409                  }                  }
2410                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
2411    
2412  // top right neighbour, if allowed  // top right neighbour, if allowed
2413                  if ((uint32_t)x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
2414                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2415                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2416                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2417                          }                          }
2418                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1650  Line 2424 
2424  */  */
2425    
2426          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2427                  || ( MVequal(*currMV,pMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2428                  {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2429                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2430                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2431                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1660  Line 2434 
2434    
2435  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
2436    
2437          backupMV = pMB->mvs[0];                 // last MV          backupMV = prevMB->mvs[0];      // collocated MV
2438          backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X          backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2439          backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y          backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2440    
2441          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
2442    
2443  // left neighbour  // left neighbour
2444          if (x != 0)          if (x != 0)
2445                  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);
2446    
2447  // top neighbour  // top neighbour
2448          if (y != 0)          if (y != 0)
2449                  CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2450                                                             (prevMB - iWcount)->mvs[0].y);
2451    
2452  // 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
2453    
2454          if ((uint32_t)x != iWcount-1)          if ((uint32_t)x != iWcount-1)
2455                  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);
2456    
2457  // bottom neighbour, dito  // bottom neighbour, dito
2458          if ((uint32_t)y != iHcount-1)          if ((uint32_t)y != iHcount-1)
2459                  CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2460                                                             (prevMB + iWcount)->mvs[0].y);
2461    
2462  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2463          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2) {
                 {  
2464                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2465                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2466                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1696  Line 2471 
2471    
2472          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2473    
 /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  
   
2474          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
2475                  EPZSMainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
2476            else
2477             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2478                    MainSearchPtr = AdvDiamond16_MainSearch;
2479          else          else
2480                  EPZSMainSearchPtr = Diamond16_MainSearch;                  MainSearchPtr = Diamond16_MainSearch;
2481    
2482          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);  
2483    
2484          if (iSAD < iMinSAD)          iSAD =
2485          {                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2486                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2487                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2488    
2489            if (iSAD < iMinSAD) {
2490                  *currMV = newMV;                  *currMV = newMV;
2491                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2492          }          }
2493    
2494    
2495          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
2496  /* 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) */
2497    
2498                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2499                  {                          iSAD =
2500                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2501                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2502                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2503                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2504                  }                  }
2505    
2506                  if (iSAD < iMinSAD)                  if (iSAD < iMinSAD) {
                 {  
2507                          *currMV = newMV;                          *currMV = newMV;
2508                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2509                  }                  }
2510    
2511                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2512                  {                          iSAD =
2513                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2514                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2515                          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);  
2516    
2517                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2518                                  *currMV = newMV;                                  *currMV = newMV;
2519                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2520                          }                          }
# Line 1752  Line 2525 
2525    
2526  EPZS16_Terminate_with_Refine:  EPZS16_Terminate_with_Refine:
2527          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
2528                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2529                                  x, y,                          Halfpel16_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  EPZS16_Terminate_without_Refine:  EPZS16_Terminate_without_Refine:
2534    
2535          *oldMB = *pMB;          *oldMB = *prevMB;
2536    
2537          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2538          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2539          return iMinSAD;          return iMinSAD;
2540  }  }
2541    
2542    
2543  int32_t EPZSSearch8(  int32_t
2544                                          const uint8_t * const pRef,  EPZSSearch8(const uint8_t * const pRef,
2545                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2546                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2547                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2548                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2549                                          const int x, const int y,                          const int x,
2550                                          const int start_x, const int start_y,                          const int y,
2551                            const int start_x,
2552                            const int start_y,
2553                            const int center_x,
2554                            const int center_y,
2555                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2556                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2557                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1784  Line 2561 
2561                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2562                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2563  {  {
2564    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
2565    
2566      const uint32_t iWcount = pParam->mb_width;      const uint32_t iWcount = pParam->mb_width;
2567          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2568          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
# Line 1806  Line 2585 
2585    
2586          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
2587    
2588          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2589          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
2590    
2591          int32_t bPredEq;          int32_t bPredEq;
2592          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2593    
2594          MainSearch8FuncPtr EPZSMainSearchPtr;          MainSearch8FuncPtr MainSearchPtr;
2595    
2596  /* Get maximum range */  /* Get maximum range */
2597          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,
2598                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2599    
2600  /* 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 */
2601    
2602          if (!(MotionFlags & PMV_HALFPEL8 ))          if (!(MotionFlags & PMV_HALFPEL8)) {
2603          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2604            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2605            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2606            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2607          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2608            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2609          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);
2610    
2611    
2612  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 1840  Line 2619 
2619  // Prepare for main loop  // Prepare for main loop
2620    
2621    
2622          if (!(MotionFlags & PMV_HALFPEL8))          if (!(MotionFlags & PMV_HALFPEL8)) {
         {  
2623                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2624                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2625          }          }
# Line 1858  Line 2636 
2636  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2637    
2638    
2639          iMinSAD = sad8( cur,          iMinSAD =
2640                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2641                  iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2642          iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                  iEdgedWidth), iEdgedWidth);
2643            iMinSAD +=
2644                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2645                                             (uint8_t) iFcode, iQuant);
2646    
2647    
2648  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2649          if (iMinSAD < 256/4 )          if (iMinSAD < 256 / 4) {
                 {  
2650                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2651                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2652                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 1875  Line 2655 
2655    
2656  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2657    
 // previous frame MV  
         CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
2658    
2659  // MV=(0,0) is often a good choice  // MV=(0,0) is often a good choice
   
2660          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2661    
2662    // previous frame MV
2663            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2664    
2665    // left neighbour, if allowed
2666            if (psad[1] != MV_MAX_ERROR) {
2667                    if (!(MotionFlags & PMV_HALFPEL8)) {
2668                            pmv[1].x = EVEN(pmv[1].x);
2669                            pmv[1].y = EVEN(pmv[1].y);
2670                    }
2671                    CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2672            }
2673    // top neighbour, if allowed
2674            if (psad[2] != MV_MAX_ERROR) {
2675                    if (!(MotionFlags & PMV_HALFPEL8)) {
2676                            pmv[2].x = EVEN(pmv[2].x);
2677                            pmv[2].y = EVEN(pmv[2].y);
2678                    }
2679                    CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2680    
2681    // top right neighbour, if allowed
2682                    if (psad[3] != MV_MAX_ERROR) {
2683                            if (!(MotionFlags & PMV_HALFPEL8)) {
2684                                    pmv[3].x = EVEN(pmv[3].x);
2685                                    pmv[3].y = EVEN(pmv[3].y);
2686                            }
2687                            CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2688                    }
2689            }
2690    
2691    /*  // this bias is zero anyway, at the moment!
2692    
2693            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2694                    iMinSAD -= MV8_00_BIAS;
2695    
2696    */
2697    
2698  /* Terminate if MinSAD <= T_2  /* Terminate if MinSAD <= T_2
2699     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]
2700  */  */
2701    
2702          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
                 {  
2703                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2704                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2705                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
2706                                  goto EPZS8_Terminate_with_Refine;                                  goto EPZS8_Terminate_with_Refine;
2707                  }                  }
2708    
2709  /************ (if Diamond Search)  **************/  /************ (Diamond Search)  **************/
2710    
2711          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2712    
2713          if (!(MotionFlags & PMV_HALFPELDIAMOND8))          if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2714                  iDiamondSize *= 2;                  iDiamondSize *= 2;
2715    
2716  /* 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 */
2717    
2718  //      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);  
2719    
2720      if (MotionFlags & PMV_USESQUARES8)
2721          MainSearchPtr = Square8_MainSearch;
2722      else
2723    
2724          if (iSAD < iMinSAD)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2725          {                  MainSearchPtr = AdvDiamond8_MainSearch;
2726            else
2727                    MainSearchPtr = Diamond8_MainSearch;
2728    
2729            iSAD =
2730                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2731                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2732                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2733                                                      iQuant, 0);
2734    
2735    
2736            if (iSAD < iMinSAD) {
2737                  *currMV = newMV;                  *currMV = newMV;
2738                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2739          }          }
2740    
2741          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2742  /* 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) */
2743    
2744                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2745                  {                          iSAD =
2746                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2747                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2748                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2749                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2750    
2751                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2752                                  *currMV = newMV;                                  *currMV = newMV;
2753                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2754                          }                          }
2755                  }                  }
2756    
2757                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2758                  {                          iSAD =
2759                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2760                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2761                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2762                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, 0);
2763    
2764                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2765                                  *currMV = newMV;                                  *currMV = newMV;
2766                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2767                          }                          }
# Line 1958  Line 2772 
2772    
2773  EPZS8_Terminate_with_Refine:  EPZS8_Terminate_with_Refine:
2774          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2775                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2776                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2777                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2778                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2779    
2780  EPZS8_Terminate_without_Refine:  EPZS8_Terminate_without_Refine:
2781    
2782          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2783          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2784          return iMinSAD;          return iMinSAD;
2785  }  }
2786    
2787    
2788    
2789    int32_t
2790    PMVfastIntSearch16(const uint8_t * const pRef,
2791                                    const uint8_t * const pRefH,
2792                                    const uint8_t * const pRefV,
2793                                    const uint8_t * const pRefHV,
2794                                    const IMAGE * const pCur,
2795                                    const int x,
2796                                    const int y,
2797                                    const int start_x,              /* start should be most likely vector */
2798                                    const int start_y,
2799                                    const int center_x,             /* center is from where length of MVs is measured */
2800                                    const int center_y,
2801                                    const uint32_t MotionFlags,
2802                                    const uint32_t iQuant,
2803                                    const uint32_t iFcode,
2804                                    const MBParam * const pParam,
2805                                    const MACROBLOCK * const pMBs,
2806                                    const MACROBLOCK * const prevMBs,
2807                                    VECTOR * const currMV,
2808                                    VECTOR * const currPMV)
2809    {
2810            const uint32_t iWcount = pParam->mb_width;
2811            const int32_t iWidth = pParam->width;
2812            const int32_t iHeight = pParam->height;
2813            const int32_t iEdgedWidth = pParam->edged_width;
2814    
2815            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2816            const VECTOR zeroMV = { 0, 0 };
2817    
2818  /* ***********************************************************          int32_t iDiamondSize;
         bvop motion estimation  
 // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)  
 ***************************************************************/  
2819    
2820  /*          int32_t min_dx;
2821  void MotionEstimationBVOP(          int32_t max_dx;
2822                          MBParam * const pParam,          int32_t min_dy;
2823                          FRAMEINFO * const frame,          int32_t max_dy;
2824    
2825                          // forward (past) reference          int32_t iFound;
2826                          const MACROBLOCK * const f_mbs,  
2827                      const IMAGE * const f_ref,          VECTOR newMV;
2828                          const IMAGE * const f_refH,          VECTOR backupMV;
2829                      const IMAGE * const f_refV,  
2830                          const IMAGE * const f_refHV,          VECTOR pmv[4];
2831                          // backward (future) reference          int32_t psad[4];
2832                          const MACROBLOCK * const b_mbs,  
2833                      const IMAGE * const b_ref,          MainSearch16FuncPtr MainSearchPtr;
2834                          const IMAGE * const b_refH,  
2835                      const IMAGE * const b_refV,          MACROBLOCK *const prevMB = (MACROBLOCK *const)prevMBs + x + y * iWcount;
2836                          const IMAGE * const b_refHV)          MACROBLOCK *const pMB = (MACROBLOCK *const)(pMBs + x + y * iWcount);