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