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

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

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