[svn] / trunk / xvidcore / src / motion / motion_est.c Repository:
ViewVC logotype

Diff of /trunk/xvidcore/src/motion/motion_est.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 78, Thu Mar 28 20:57:25 2002 UTC revision 345, Sat Jul 27 23:47:01 2002 UTC
# Line 1  Line 1 
1  /**************************************************************************  /**************************************************************************
2   *   *
3     *      XVID MPEG-4 VIDEO CODEC
4     *      motion estimation
5     *
6     *      This program is an implementation of a part of one or more MPEG-4
7     *      Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
8     *      to use this software module in hardware or software products are
9     *      advised that its use may infringe existing patents or copyrights, and
10     *      any such use would be at such party's own risk.  The original
11     *      developer of this software module and his/her company, and subsequent
12     *      editors and their companies, will have no liability for use of this
13     *      software or modifications or derivatives thereof.
14     *
15     *      This program is free software; you can redistribute it and/or modify
16     *      it under the terms of the GNU General Public License as published by
17     *      the Free Software Foundation; either version 2 of the License, or
18     *      (at your option) any later version.
19     *
20     *      This program is distributed in the hope that it will be useful,
21     *      but WITHOUT ANY WARRANTY; without even the implied warranty of
22     *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     *      GNU General Public License for more details.
24     *
25     *      You should have received a copy of the GNU General Public License
26     *      along with this program; if not, write to the Free Software
27     *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28     *
29     *************************************************************************/
30    
31    /**************************************************************************
32     *
33   *  Modifications:   *  Modifications:
34   *   *
35     *      01.05.2002      updated MotionEstimationBVOP
36     *      25.04.2002 partial prevMB conversion
37     *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>
38     *  14.04.2002 added MotionEstimationBVOP()
39     *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between
40     *             EPZS and EPZS^2
41   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop
42   *             PMVFast_Refine to support multiple searches with different start points   *             PMVFast_Refine to support multiple searches with different start points
43   *  07.01.2002 uv-block-based interpolation   *  07.01.2002 uv-block-based interpolation
# Line 31  Line 67 
67    
68  #include <assert.h>  #include <assert.h>
69  #include <stdio.h>  #include <stdio.h>
70    #include <stdlib.h>
71    
72  #include "../encoder.h"  #include "../encoder.h"
73  #include "../utils/mbfunctions.h"  #include "../utils/mbfunctions.h"
74  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
75  #include "../global.h"  #include "../global.h"
76  #include "../utils/timer.h"  #include "../utils/timer.h"
77    #include "motion.h"
78  #include "sad.h"  #include "sad.h"
79    
 // 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)  
   
   
 #define MIN(X, Y) ((X)<(Y)?(X):(Y))  
 #define MAX(X, Y) ((X)>(Y)?(X):(Y))  
 #define ABS(X)    (((X)>0)?(X):-(X))  
 #define SIGN(X)   (((X)>0)?1:-1)  
   
   
 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, int start_y,  
         const uint32_t iQuality,  
         MBParam * const pParam,  
         MACROBLOCK * const pMBs,  
         VECTOR * const currMV,  
         VECTOR * const currPMV);  
   
 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 iQuality,  
         MBParam * const pParam,  
         MACROBLOCK * const pMBs,  
         VECTOR * const currMV,  
         VECTOR * const currPMV);  
   
   
   
 /*  
  * diamond search stuff  
  * keep the the sequence in circular order (so optimization works)  
  */  
   
 typedef struct  
 {  
         int32_t dx;  
         int32_t dy;  
 }  
 DPOINT;  
80    
81    
82  static const DPOINT diamond_small[4] =  static int32_t lambda_vec16[32] =       /* rounded values for lambda param for weight of motion bits as in modified H.26L */
83  {  { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),
84          {0, 1}, {1, 0}, {0, -1}, {-1, 0}                  (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),
85            (int) (1.89187 + 0.5), (int) (2.11542 + 0.5), (int) (2.35878 + 0.5),
86                    (int) (2.62429 + 0.5), (int) (2.91455 + 0.5),
87            (int) (3.23253 + 0.5), (int) (3.58158 + 0.5), (int) (3.96555 + 0.5),
88                    (int) (4.38887 + 0.5), (int) (4.85673 + 0.5),
89            (int) (5.37519 + 0.5), (int) (5.95144 + 0.5), (int) (6.59408 + 0.5),
90                    (int) (7.31349 + 0.5), (int) (8.12242 + 0.5),
91            (int) (9.03669 + 0.5), (int) (10.0763 + 0.5), (int) (11.2669 + 0.5),
92                    (int) (12.6426 + 0.5), (int) (14.2493 + 0.5),
93            (int) (16.1512 + 0.5), (int) (18.442 + 0.5), (int) (21.2656 + 0.5),
94                    (int) (24.8580 + 0.5), (int) (29.6436 + 0.5),
95            (int) (36.4949 + 0.5)
96  };  };
97    
98    static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now */
99    
 static const DPOINT diamond_large[8] =  
 {  
         {0, 2}, {1, 1}, {2, 0}, {1, -1}, {0, -2}, {-1, -1}, {-2, 0}, {-1, 1}  
 };  
100    
101    
102  // mv.length table  // mv.length table
# Line 134  Line 108 
108  };  };
109    
110    
111  static __inline uint32_t mv_bits(int32_t component, const uint32_t iFcode)  static __inline uint32_t
112    mv_bits(int32_t component,
113                    const uint32_t iFcode)
114  {  {
115      if (component == 0)      if (component == 0)
116                  return 1;                  return 1;
# Line 142  Line 118 
118      if (component < 0)      if (component < 0)
119                  component = -component;                  component = -component;
120    
121      if (iFcode == 1)          if (iFcode == 1) {
     {  
122                  if (component > 32)                  if (component > 32)
123                      component = 32;                      component = 32;
124    
# Line 160  Line 135 
135  }  }
136    
137    
138  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode)  static __inline uint32_t
139  {  calc_delta_16(const int32_t dx,
140          return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));                            const int32_t dy,
141  }                            const uint32_t iFcode,
142                              const uint32_t iQuant)
143  static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)  {
144            return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) +
145  {                                                                                                            mv_bits(dy, iFcode));
146      return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));  }
147  }  
148    static __inline uint32_t
149    calc_delta_8(const int32_t dx,
150                             const int32_t dy,
151                             const uint32_t iFcode,
152  /* calculate the min/max range (in halfpixels)                           const uint32_t iQuant)
153          relative to the _MACROBLOCK_ position  {
154  */          return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) +
155                                                                                                       mv_bits(dy, iFcode));
156  static void __inline get_range(  }
157          int32_t * const min_dx, int32_t * const max_dx,  
158          int32_t * const min_dy, int32_t * const max_dy,  bool
159          const uint32_t x, const uint32_t y,  MotionEstimation(MBParam * const pParam,
160          const uint32_t block_sz,                                        // block dimension, 8 or 16                                   FRAMEINFO * const current,
161          const uint32_t width, const uint32_t height,                                   FRAMEINFO * const reference,
         const uint32_t fcode)  
 {  
   
         const int search_range = 32 << (fcode - 1);  
         const int high = search_range - 1;  
         const int low = -search_range;  
   
         // convert full-pixel measurements to half pixel  
         const int hp_width = 2 * width;  
         const int hp_height = 2 * height;  
         const int hp_edge = 2 * block_sz;  
         const int hp_x = 2 * (x) * block_sz;            // we need _right end_ of block, not x-coordinate  
         const int hp_y = 2 * (y) * block_sz;            // same for _bottom end_  
   
         *max_dx = MIN(high,     hp_width - hp_x);  
         *max_dy = MIN(high,     hp_height - hp_y);  
         *min_dx = MAX(low,      -(hp_edge + hp_x));  
         *min_dy = MAX(low,      -(hp_edge + hp_y));  
   
 }  
   
   
 /*  
  * getref: calculate reference image pointer  
  * the decision to use interpolation h/v/hv or the normal image is  
  * based on dx & dy.  
  */  
   
 static __inline const uint8_t * get_ref(  
         const uint8_t * const refn,  
         const uint8_t * const refh,  
         const uint8_t * const refv,  
         const uint8_t * const refhv,  
         const uint32_t x, const uint32_t y,  
         const uint32_t block,                                   // block dimension, 8 or 16  
         const int32_t dx, const int32_t dy,  
         const uint32_t stride)  
 {  
   
         switch ( ((dx&1)<<1) + (dy&1) )         // ((dx%2)?2:0)+((dy%2)?1:0)  
         {  
         case 0  : return refn + (x*block+dx/2) + (y*block+dy/2)*stride;  
         case 1  : return refv + (x*block+dx/2) + (y*block+(dy-1)/2)*stride;  
         case 2  : return refh + (x*block+(dx-1)/2) + (y*block+dy/2)*stride;  
         default :  
         case 3  : return refhv + (x*block+(dx-1)/2) + (y*block+(dy-1)/2)*stride;  
         }  
   
 }  
   
   
 /* This is somehow a copy of get_ref, but with MV instead of X,Y */  
   
 static __inline const uint8_t * get_ref_mv(  
         const uint8_t * const refn,  
         const uint8_t * const refh,  
         const uint8_t * const refv,  
         const uint8_t * const refhv,  
         const uint32_t x, const uint32_t y,  
         const uint32_t block,                   // block dimension, 8 or 16  
         const VECTOR* mv,       // measured in half-pel!  
         const uint32_t stride)  
 {  
   
         switch ( (((mv->x)&1)<<1) + ((mv->y)&1) )  
         {  
         case 0  : return refn + (x*block+(mv->x)/2) + (y*block+(mv->y)/2)*stride;  
         case 1  : return refv + (x*block+(mv->x)/2) + (y*block+((mv->y)-1)/2)*stride;  
         case 2  : return refh + (x*block+((mv->x)-1)/2) + (y*block+(mv->y)/2)*stride;  
         default :  
         case 3  : return refhv + (x*block+((mv->x)-1)/2) + (y*block+((mv->y)-1)/2)*stride;  
         }  
   
 }  
   
 #ifndef SEARCH16  
 #define SEARCH16        PMVfastSearch16  
 #endif  
   
 #ifndef SEARCH8  
 #define SEARCH8         PMVfastSearch8  
 #endif  
   
 bool MotionEstimation(  
         MACROBLOCK * const pMBs,  
         MBParam * const pParam,  
         const IMAGE * const pRef,  
162          const IMAGE * const pRefH,          const IMAGE * const pRefH,
163          const IMAGE * const pRefV,          const IMAGE * const pRefV,
164          const IMAGE * const pRefHV,          const IMAGE * const pRefHV,
         IMAGE * const pCurrent,  
165          const uint32_t iLimit)          const uint32_t iLimit)
   
166  {  {
167          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
168          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
169            MACROBLOCK *const pMBs = current->mbs;
170            MACROBLOCK *const prevMBs = reference->mbs;
171            const IMAGE *const pCurrent = &current->image;
172            const IMAGE *const pRef = &reference->image;
173    
174          uint32_t i, j, iIntra = 0;          static const VECTOR zeroMV = { 0, 0 };
175            VECTOR predMV;
176    
177          VECTOR mv16;          int32_t x, y;
178          VECTOR pmv16;          int32_t iIntra = 0;
179            VECTOR pmv;
180    
181          int32_t sad8 = 0;          if (sadInit)
182          int32_t sad16;                  (*sadInit) ();
         int32_t deviation;  
183    
184          // note: i==horizontal, j==vertical          for (y = 0; y < iHcount; y++)   {
185          for (i = 0; i < iHcount; i++)                  for (x = 0; x < iWcount; x ++)  {
                 for (j = 0; j < iWcount; j++)  
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
186    
187                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
                                          j, i, pParam->motion_flags,  
                                          pParam, pMBs, &mv16, &pmv16);  
                         pMB->sad16=sad16;  
188    
189                            predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
190    
191                          /* decide: MODE_INTER or MODE_INTRA                          pMB->sad16 =
192                             if (dev_intra < sad_inter - 2 * nb) use_intra                                  SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
193                          */                                                   x, y, predMV.x, predMV.y, predMV.x, predMV.y,
194                                                     current->motion_flags, current->quant,
195                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
196                                                     &pMB->pmvs[0]);
197    
198                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                          if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
199                                    int32_t deviation;
200    
201                          if (deviation < (sad16 - INTER_BIAS))                                  deviation =
202                          {                                          dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
203                                                      pParam->edged_width);
204    
205                                    if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
206                                  pMB->mode = MODE_INTRA;                                  pMB->mode = MODE_INTRA;
207                                  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] =
208                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                                  pMB->mvs[3] = zeroMV;
209                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
210                                                    pMB->sad8[3] = 0;
211    
212                                  iIntra++;                                  iIntra++;
213                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 320  Line 215 
215    
216                                  continue;                                  continue;
217                          }                          }
   
                         if (pParam->global_flags & XVID_INTER4V)  
                         {  
                                 pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j, 2 * i, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[0], &pMB->pmvs[0]);  
   
                                 pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j + 1, 2 * i, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[1], &pMB->pmvs[1]);  
   
                                 pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[2], &pMB->pmvs[2]);  
   
                                 pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j + 1, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[3], &pMB->pmvs[3]);  
   
                                 sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];  
218                          }                          }
219    
220                            pmv = pMB->pmvs[0];
221                            if (current->global_flags & XVID_INTER4V)
222                                    if ((!(current->global_flags & XVID_LUMIMASKING) ||
223                                             pMB->dquant == NO_CHANGE)) {
224                                            int32_t sad8 = IMV16X16 * current->quant;
225    
226                                            if (sad8 < pMB->sad16) {
227                                                    sad8 += pMB->sad8[0] =
228                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
229                                                                            pCurrent, 2 * x, 2 * y,
230                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
231                                                                            current->motion_flags,
232                                                                            current->quant, current->fcode, pParam,
233                                                                            pMBs, prevMBs, &pMB->mvs[0],
234                                                                            &pMB->pmvs[0]);
235                                            }
236                                            if (sad8 < pMB->sad16) {
237    
238                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
239                                                    sad8 += pMB->sad8[1] =
240                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
241                                                                            pCurrent, 2 * x + 1, 2 * y,
242                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
243                                                                            current->motion_flags,
244                                                                            current->quant, current->fcode, pParam,
245                                                                            pMBs, prevMBs, &pMB->mvs[1],
246                                                                            &pMB->pmvs[1]);
247                                            }
248                                            if (sad8 < pMB->sad16) {
249                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
250                                                    sad8 += pMB->sad8[2] =
251                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
252                                                                            pCurrent, 2 * x, 2 * y + 1,
253                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
254                                                                            current->motion_flags,
255                                                                            current->quant, current->fcode, pParam,
256                                                                            pMBs, prevMBs, &pMB->mvs[2],
257                                                                            &pMB->pmvs[2]);
258                                            }
259                                            if (sad8 < pMB->sad16) {
260                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
261                                                    sad8 += pMB->sad8[3] =
262                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
263                                                                            pCurrent, 2 * x + 1, 2 * y + 1,
264                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
265                                                                            current->motion_flags,
266                                                                            current->quant, current->fcode, pParam,
267                                                                            pMBs, prevMBs,
268                                                                            &pMB->mvs[3],
269                                                                            &pMB->pmvs[3]);
270                                            }
271    
272                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
273                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
274                          */                          */
275    
276                          if (pMB->dquant == NO_CHANGE) {                                          if (sad8 < pMB->sad16) {
                                 if (((pParam->global_flags & XVID_INTER4V)==0) ||  
                                     (sad16 < (sad8 + (int32_t)(IMV16X16 * pParam->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  
277                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
278                                                    pMB->sad8[0] *= 4;
279                                                    pMB->sad8[1] *= 4;
280                                                    pMB->sad8[2] *= 4;
281                                                    pMB->sad8[3] *= 4;
282                                                    continue;
283                          }                          }
284                          else  
285                          {                                  }
286                                  sad8 = sad16;  
287                                  pMB->mode = MODE_INTER;                                  pMB->mode = MODE_INTER;
288                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;                          pMB->pmvs[0] = pmv;     /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
289                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
290                                  pMB->pmvs[0].x = pmv16.x;                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
291                                  pMB->pmvs[0].y = pmv16.y;                                  pMB->sad16;
292                          }                          }
293                  }                  }
294    
295          return 0;          return 0;
296  }  }
297    
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
   
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
298    
299  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
300    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
301      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
302    { \    { \
303      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); \
304      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; \  
305      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
306      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
307  }  }
308    
309    #define NOCHECK_MV16_CANDIDATE(X,Y) { \
310        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
311        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
312        if (iSAD < iMinSAD) \
313        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
314    }
315    
316  #define CHECK_MV16_CANDIDATE(X,Y) { \  #define CHECK_MV16_CANDIDATE(X,Y) { \
317    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
318      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
319    { \    { \
320      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); \
321      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);\
322      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
323      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
324  }  }
# Line 408  Line 328 
328      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
329    { \    { \
330      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); \
331      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);\
332      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
333      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
334  }  }
# Line 418  Line 338 
338      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
339    { \    { \
340      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); \
341      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);\
342      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
343      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
344  }  }
# Line 426  Line 346 
346    
347  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
348    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); \
349    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);\
350    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
351    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
352  }  }
353    
354    #define NOCHECK_MV8_CANDIDATE(X,Y) \
355      { \
356        iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
357        iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
358        if (iSAD < iMinSAD) \
359        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
360    }
361    
362  #define CHECK_MV8_CANDIDATE(X,Y) { \  #define CHECK_MV8_CANDIDATE(X,Y) { \
363    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
364      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
365    { \    { \
366      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); \
367      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);\
368      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
369      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
370  }  }
# Line 447  Line 374 
374      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
375    { \    { \
376      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); \
377      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);\
378      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
379      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
380  }  }
# Line 457  Line 384 
384      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
385    { \    { \
386      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); \
387      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);\
388      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
389      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
390  }  }
# Line 472  Line 399 
399                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
400                                          const int x, const int y,                                          const int x, const int y,
401                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
402                                            const uint32_t iQuant,
403                                            const uint32_t iFcode,
404                                          MBParam * const pParam,                                          MBParam * const pParam,
405                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
406                                            const MACROBLOCK * const prevMBs,
407                                          VECTOR * const currMV,                                          VECTOR * const currMV,
408                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
409  {  {
410          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
411          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
412          int32_t iSAD;          int32_t iSAD;
413          int32_t pred_x,pred_y;          VECTOR pred;
414    
415    
416          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
417    
418          iSAD = sad16( cur,          iSAD = sad16( cur,
419                  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 493  Line 423 
423    
424          currMV->x = 0;          currMV->x = 0;
425          currMV->y = 0;          currMV->y = 0;
426          currPMV->x = -pred_x;          currPMV->x = -pred.x;
427          currPMV->y = -pred_y;          currPMV->y = -pred.y;
428    
429          return iSAD;          return iSAD;
430    
431  }  }
432  */  */
433    
434  int32_t PMVfastSearch16_MainSearch(  int32_t
435          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
436          const uint8_t * const pRefH,          const uint8_t * const pRefH,
437          const uint8_t * const pRefV,          const uint8_t * const pRefV,
438          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
439          const uint8_t * const cur,          const uint8_t * const cur,
440          const int x, const int y,                                           const int x,
441          int32_t startx, int32_t starty,                                           const int y,
442          int32_t iMinSAD,                                     const int start_x,
443                                       const int start_y,
444                                       int iMinSAD,
445          VECTOR * const currMV,          VECTOR * const currMV,
446          const VECTOR * const pmv,                                     const int center_x,
447          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
448          const int32_t min_dy, const int32_t max_dy,                                           const int32_t min_dx,
449                                             const int32_t max_dx,
450                                             const int32_t min_dy,
451                                             const int32_t max_dy,
452          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
453          const int32_t iDiamondSize,          const int32_t iDiamondSize,
454          const int32_t iFcode,          const int32_t iFcode,
# Line 523  Line 458 
458  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
459    
460          int32_t iDirection=0;          int32_t iDirection=0;
461            int32_t iDirectionBackup;
462          int32_t iSAD;          int32_t iSAD;
463          VECTOR backupMV;          VECTOR backupMV;
464          backupMV.x = startx;  
465          backupMV.y = starty;          backupMV.x = start_x;
466            backupMV.y = start_y;
467    
468  /* 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 */
469    
# Line 535  Line 472 
472          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
473          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
474    
475          if (iDirection)          if (iDirection) {
476                  while (!iFound)                  while (!iFound) {
                 {  
477                          iFound = 1;                          iFound = 1;
478                          backupMV=*currMV;                          backupMV=*currMV;
479                            iDirectionBackup = iDirection;
480    
481                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
482                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
483                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
484                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
485                          if ( iDirection != 4)                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
486                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                     backupMV.y, 2);
487                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
488                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
489                                                                                       backupMV.y - iDiamondSize, 3);
490                            if (iDirectionBackup != 3)
491                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
492                                                                                       backupMV.y + iDiamondSize, 4);
493                  }                  }
494          else          } else {
495          {                  currMV->x = start_x;
496                  currMV->x = startx;                  currMV->y = start_y;
                 currMV->y = starty;  
497          }          }
498          return iMinSAD;          return iMinSAD;
499  }  }
500    
501  int32_t PMVfastSearch16_Refine(  int32_t
502          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
503          const uint8_t * const pRefH,          const uint8_t * const pRefH,
504          const uint8_t * const pRefV,          const uint8_t * const pRefV,
505          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
506          const uint8_t * const cur,          const uint8_t * const cur,
507          const int x, const int y,                                          const int x,
508                                            const int y,
509                                       const int start_x,
510                                       const int start_y,
511                                       int iMinSAD,
512          VECTOR * const currMV,          VECTOR * const currMV,
513          int32_t iMinSAD,                                     const int center_x,
514          const VECTOR * const pmv,                                     const int center_y,
515          const int32_t min_dx, const int32_t max_dx,                                          const int32_t min_dx,
516          const int32_t min_dy, const int32_t max_dy,                                          const int32_t max_dx,
517                                            const int32_t min_dy,
518                                            const int32_t max_dy,
519                                            const int32_t iEdgedWidth,
520                                            const int32_t iDiamondSize,
521          const int32_t iFcode,          const int32_t iFcode,
522          const int32_t iQuant,          const int32_t iQuant,
523          const int32_t iEdgedWidth)                                          int iFound)
524  {  {
525  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a square search around given starting point, return SAD of best */
526    
527            int32_t iDirection = 0;
528          int32_t iSAD;          int32_t iSAD;
529          VECTOR backupMV = *currMV;          VECTOR backupMV;
530    
531          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);          backupMV.x = start_x;
532          CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);          backupMV.y = start_y;
533          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);  
534          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);  /* It's one search with full square pattern, and new parts for all following diamonds */
535          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);  
536          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);  /*   new direction are extra, so 1-4 is normal diamond
537          CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);        537
538          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);        1*2
539          648
540    */
541    
542            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
543            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
544            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
545            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
546    
547            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
548                                                             backupMV.y - iDiamondSize, 5);
549            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
550                                                             backupMV.y + iDiamondSize, 6);
551            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
552                                                             backupMV.y - iDiamondSize, 7);
553            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
554                                                             backupMV.y + iDiamondSize, 8);
555    
556    
557            if (iDirection) {
558                    while (!iFound) {
559                            iFound = 1;
560                            backupMV = *currMV;
561    
562                            switch (iDirection) {
563                            case 1:
564                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
565                                                                                       backupMV.y, 1);
566                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
567                                                                                     backupMV.y - iDiamondSize, 5);
568                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
569                                                                                     backupMV.y - iDiamondSize, 7);
570                                    break;
571                            case 2:
572                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
573                                                                                     2);
574                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
575                                                                                     backupMV.y + iDiamondSize, 6);
576                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
577                                                                                     backupMV.y + iDiamondSize, 8);
578                                    break;
579    
580                            case 3:
581                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
582                                                                                     4);
583                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
584                                                                                     backupMV.y - iDiamondSize, 7);
585                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
586                                                                                     backupMV.y + iDiamondSize, 8);
587                                    break;
588    
589                            case 4:
590                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
591                                                                                     3);
592                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
593                                                                                     backupMV.y - iDiamondSize, 5);
594                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
595                                                                                     backupMV.y + iDiamondSize, 6);
596                                    break;
597    
598                            case 5:
599                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
600                                                                                     1);
601                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
602                                                                                     3);
603                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
604                                                                                     backupMV.y - iDiamondSize, 5);
605                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
606                                                                                     backupMV.y + iDiamondSize, 6);
607                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
608                                                                                     backupMV.y - iDiamondSize, 7);
609                                    break;
610    
611                            case 6:
612                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
613                                                                                     2);
614                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
615                                                                                     3);
616    
617                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
618                                                                                     backupMV.y - iDiamondSize, 5);
619                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
620                                                                                     backupMV.y + iDiamondSize, 6);
621                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
622                                                                                     backupMV.y + iDiamondSize, 8);
623    
624                                    break;
625    
626                            case 7:
627                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
628                                                                                       backupMV.y, 1);
629                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
630                                                                                     4);
631                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
632                                                                                     backupMV.y - iDiamondSize, 5);
633                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
634                                                                                     backupMV.y - iDiamondSize, 7);
635                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
636                                                                                     backupMV.y + iDiamondSize, 8);
637                                    break;
638    
639                            case 8:
640                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
641                                                                                     2);
642                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
643                                                                                     4);
644                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
645                                                                                     backupMV.y + iDiamondSize, 6);
646                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
647                                                                                     backupMV.y - iDiamondSize, 7);
648                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
649                                                                                     backupMV.y + iDiamondSize, 8);
650                                    break;
651                            default:
652                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
653                                                                                     1);
654                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
655                                                                                     2);
656                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
657                                                                                     3);
658                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
659                                                                                     4);
660    
661                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
662                                                                                     backupMV.y - iDiamondSize, 5);
663                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
664                                                                                     backupMV.y + iDiamondSize, 6);
665                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
666                                                                                     backupMV.y - iDiamondSize, 7);
667                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
668                                                                                     backupMV.y + iDiamondSize, 8);
669                                    break;
670                            }
671                    }
672            } else {
673                    currMV->x = start_x;
674                    currMV->y = start_y;
675            }
676          return iMinSAD;          return iMinSAD;
677  }  }
678    
 #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  
679    
680  int32_t PMVfastSearch16(  int32_t
681          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
682          const uint8_t * const pRefH,          const uint8_t * const pRefH,
683          const uint8_t * const pRefV,          const uint8_t * const pRefV,
684          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
685          const IMAGE * const pCur,                                    const uint8_t * const cur,
686          const int x, const int y,                                    const int x,
687          const uint32_t MotionFlags,                                    const int y,
688          MBParam * const pParam,                                     const int start_x,
689          MACROBLOCK * const pMBs,                                     const int start_y,
690                                       int iMinSAD,
691          VECTOR * const currMV,          VECTOR * const currMV,
692          VECTOR * const currPMV)                                     const int center_x,
693                                       const int center_y,
694                                      const int32_t min_dx,
695                                      const int32_t max_dx,
696                                      const int32_t min_dy,
697                                      const int32_t max_dy,
698                                      const int32_t iEdgedWidth,
699                                      const int32_t iDiamondSize,
700                                      const int32_t iFcode,
701                                      const int32_t iQuant,
702                                      int iFound)
703  {  {
704          const uint32_t iWcount = pParam->mb_width;          int32_t iSAD;
705          const int32_t iFcode = pParam->fixed_code;          int32_t dx, dy;
706          const int32_t iQuant = pParam->quant;          VECTOR backupMV;
         const int32_t iWidth = pParam->width;  
         const int32_t iHeight = pParam->height;  
         const int32_t iEdgedWidth = pParam->edged_width;  
   
         const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;  
707    
708          int32_t iDiamondSize;          backupMV.x = start_x;
709            backupMV.y = start_y;
710    
711          int32_t min_dx;          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
712          int32_t max_dx;                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
713          int32_t min_dy;                          NOCHECK_MV16_CANDIDATE(dx, dy);
         int32_t max_dy;  
714    
715          int32_t iFound;          return iMinSAD;
716    }
717    
718          VECTOR newMV;  int32_t
719          VECTOR backupMV;        /* just for PMVFAST */  AdvDiamond16_MainSearch(const uint8_t * const pRef,
720                                                    const uint8_t * const pRefH,
721                                                    const uint8_t * const pRefV,
722                                                    const uint8_t * const pRefHV,
723                                                    const uint8_t * const cur,
724                                                    const int x,
725                                                    const int y,
726                                               int start_x,
727                                               int start_y,
728                                               int iMinSAD,
729                                               VECTOR * const currMV,
730                                               const int center_x,
731                                               const int center_y,
732                                                    const int32_t min_dx,
733                                                    const int32_t max_dx,
734                                                    const int32_t min_dy,
735                                                    const int32_t max_dy,
736                                                    const int32_t iEdgedWidth,
737                                                    const int32_t iDiamondSize,
738                                                    const int32_t iFcode,
739                                                    const int32_t iQuant,
740                                                    int iDirection)
741    {
742    
743          VECTOR pmv[4];          int32_t iSAD;
         int32_t psad[4];  
744    
745          MACROBLOCK * const pMB = pMBs + x + y * iWcount;  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
746    
747          static int32_t threshA,threshB;          if (iDirection) {
748          int32_t bPredEq;                  CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
749          int32_t iMinSAD,iSAD;                  CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
750                    CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
751                    CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
752            } else {
753                    int bDirection = 1 + 2 + 4 + 8;
754    
755                    do {
756                            iDirection = 0;
757                            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)
758                                    CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
759    
760                            if (bDirection & 2)
761                                    CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
762    
763                            if (bDirection & 4)
764                                    CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
765    
766                            if (bDirection & 8)
767                                    CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
768    
769                            /* now we're doing diagonal checks near our candidate */
770    
771                            if (iDirection)         //checking if anything found
772                            {
773                                    bDirection = iDirection;
774                                    iDirection = 0;
775                                    start_x = currMV->x;
776                                    start_y = currMV->y;
777                                    if (bDirection & 3)     //our candidate is left or right
778                                    {
779                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
780                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
781                                    } else                  // what remains here is up or down
782                                    {
783                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
784                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
785                                    }
786    
787                                    if (iDirection) {
788                                            bDirection += iDirection;
789                                            start_x = currMV->x;
790                                            start_y = currMV->y;
791                                    }
792                            } else                          //about to quit, eh? not so fast....
793                            {
794                                    switch (bDirection) {
795                                    case 2:
796                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
797                                                                                             start_y - iDiamondSize, 2 + 4);
798                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
799                                                                                             start_y + iDiamondSize, 2 + 8);
800                                            break;
801                                    case 1:
802    
803                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
804                                                                                             start_y - iDiamondSize, 1 + 4);
805                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
806                                                                                             start_y + iDiamondSize, 1 + 8);
807                                            break;
808                                    case 2 + 4:
809                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
810                                                                                             start_y - iDiamondSize, 1 + 4);
811                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
812                                                                                             start_y - iDiamondSize, 2 + 4);
813                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
814                                                                                             start_y + iDiamondSize, 2 + 8);
815                                            break;
816                                    case 4:
817                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
818                                                                                             start_y - iDiamondSize, 2 + 4);
819                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
820                                                                                             start_y - iDiamondSize, 1 + 4);
821                                            break;
822                                    case 8:
823                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
824                                                                                             start_y + iDiamondSize, 2 + 8);
825                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
826                                                                                             start_y + iDiamondSize, 1 + 8);
827                                            break;
828                                    case 1 + 4:
829                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
830                                                                                             start_y + iDiamondSize, 1 + 8);
831                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
832                                                                                             start_y - iDiamondSize, 1 + 4);
833                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
834                                                                                             start_y - iDiamondSize, 2 + 4);
835                                            break;
836                                    case 2 + 8:
837                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
838                                                                                             start_y - iDiamondSize, 1 + 4);
839                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
840                                                                                             start_y + iDiamondSize, 1 + 8);
841                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
842                                                                                             start_y + iDiamondSize, 2 + 8);
843                                            break;
844                                    case 1 + 8:
845                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
846                                                                                             start_y - iDiamondSize, 2 + 4);
847                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
848                                                                                             start_y + iDiamondSize, 2 + 8);
849                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
850                                                                                             start_y + iDiamondSize, 1 + 8);
851                                            break;
852                                    default:                //1+2+4+8 == we didn't find anything at all
853                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
854                                                                                             start_y - iDiamondSize, 1 + 4);
855                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
856                                                                                             start_y + iDiamondSize, 1 + 8);
857                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
858                                                                                             start_y - iDiamondSize, 2 + 4);
859                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
860                                                                                             start_y + iDiamondSize, 2 + 8);
861                                            break;
862                                    }
863                                    if (!iDirection)
864                                            break;          //ok, the end. really
865                                    else {
866                                            bDirection = iDirection;
867                                            start_x = currMV->x;
868                                            start_y = currMV->y;
869                                    }
870                            }
871                    }
872                    while (1);                              //forever
873            }
874            return iMinSAD;
875    }
876    
 /* Get maximum range */  
         get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                   x, y, 16, iWidth, iHeight, iFcode);  
877    
878  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  #define CHECK_MV16_F_INTERPOL(X,Y,BX,BY) { \
879      if ( ((X) <= max_dx) && ((X) >= min_dx) \
880        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
881      { \
882        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
883        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
884        if (iSAD < iMinSAD) \
885        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
886    }
887    
888          if (!(MotionFlags & PMV_HALFPEL16 ))  #define CHECK_MV16_F_INTERPOL_DIR(X,Y,BX,BY,D) { \
889          { min_dx = EVEN(min_dx);    if ( ((X) <= max_dx) && ((X) >= min_dx) \
890          max_dx = EVEN(max_dx);      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
891          min_dy = EVEN(min_dy);    { \
892          max_dy = EVEN(max_dy);      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
893          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
894        if (iSAD < iMinSAD) \
895        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
896    }
897    
898    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y,BX,BY,D) { \
899      if ( ((X) <= max_dx) && ((X) >= min_dx) \
900        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
901      { \
902        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
903        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
904        if (iSAD < iMinSAD) \
905        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
906    }
907    
         bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);  
908    
909          if ((x==0) && (y==0) )  #define CHECK_MV16_B_INTERPOL(FX,FY,X,Y) { \
910          {    if ( ((X) <= max_dx) && ((X) >= min_dx) \
911                  threshA =  512;      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
912                  threshB = 1024;    { \
913        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
914        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
915        if (iSAD < iMinSAD) \
916        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
917    }
918    
919    
920    #define CHECK_MV16_B_INTERPOL_DIR(FX,FY,X,Y,D) { \
921      if ( ((X) <= max_dx) && ((X) >= min_dx) \
922        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
923      { \
924        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
925        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
926        if (iSAD < iMinSAD) \
927        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
928          }          }
929          else  
930    
931    #define CHECK_MV16_B_INTERPOL_FOUND(FX,FY,X,Y,D) { \
932      if ( ((X) <= max_dx) && ((X) >= min_dx) \
933        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
934      { \
935        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
936        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
937        if (iSAD < iMinSAD) \
938        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
939    }
940    
941    
942    #if (0==1)
943    int32_t
944    Diamond16_InterpolMainSearch(
945                                            const uint8_t * const f_pRef,
946                                             const uint8_t * const f_pRefH,
947                                             const uint8_t * const f_pRefV,
948                                             const uint8_t * const f_pRefHV,
949                                             const uint8_t * const cur,
950    
951                                            const uint8_t * const b_pRef,
952                                             const uint8_t * const b_pRefH,
953                                             const uint8_t * const b_pRefV,
954                                             const uint8_t * const b_pRefHV,
955    
956                                             const int x,
957                                             const int y,
958    
959                                       const int f_start_x,
960                                       const int f_start_y,
961                                       const int b_start_x,
962                                       const int b_start_y,
963    
964                                       int iMinSAD,
965                                       VECTOR * const f_currMV,
966                                       VECTOR * const b_currMV,
967    
968                                       const int f_center_x,
969                                       const int f_center_y,
970                                       const int b_center_x,
971                                       const int b_center_y,
972    
973                                             const int32_t min_dx,
974                                             const int32_t max_dx,
975                                             const int32_t min_dy,
976                                             const int32_t max_dy,
977                                             const int32_t iEdgedWidth,
978                                             const int32_t iDiamondSize,
979    
980                                             const int32_t f_iFcode,
981                                             const int32_t b_iFcode,
982    
983                                             const int32_t iQuant,
984                                             int iFound)
985          {          {
986                  threshA = psad[0];  /* Do a diamond search around given starting point, return SAD of best */
987                  threshB = threshA+256;  
988                  if (threshA< 512) threshA =  512;          int32_t f_iDirection = 0;
989                  if (threshA>1024) threshA = 1024;          int32_t b_iDirection = 0;
990                  if (threshB>1792) threshB = 1792;          int32_t iSAD;
991    
992            VECTOR f_backupMV;
993            VECTOR b_backupMV;
994    
995            f_backupMV.x = start_x;
996            f_backupMV.y = start_y;
997            b_backupMV.x = start_x;
998            b_backupMV.y = start_y;
999    
1000    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1001    
1002            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1003            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1004            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1005            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1006    
1007            if (iDirection)
1008                    while (!iFound) {
1009                            iFound = 1;
1010                            backupMV = *currMV;
1011    
1012                            if (iDirection != 2)
1013                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1014                                                                                       backupMV.y, 1);
1015                            if (iDirection != 1)
1016                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1017                                                                                       backupMV.y, 2);
1018                            if (iDirection != 4)
1019                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1020                                                                                       backupMV.y - iDiamondSize, 3);
1021                            if (iDirection != 3)
1022                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1023                                                                                       backupMV.y + iDiamondSize, 4);
1024            } else {
1025                    currMV->x = start_x;
1026                    currMV->y = start_y;
1027            }
1028            return iMinSAD;
1029          }          }
1030    #endif
1031    
         iFound=0;  
1032    
1033  /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  int32_t
1034     vector of the median.  AdvDiamond8_MainSearch(const uint8_t * const pRef,
1035     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2                                             const uint8_t * const pRefH,
1036  */                                             const uint8_t * const pRefV,
1037                                               const uint8_t * const pRefHV,
1038                                               const uint8_t * const cur,
1039                                               const int x,
1040                                               const int y,
1041                                               int start_x,
1042                                               int start_y,
1043                                               int iMinSAD,
1044                                               VECTOR * const currMV,
1045                                               const int center_x,
1046                                               const int center_y,
1047                                               const int32_t min_dx,
1048                                               const int32_t max_dx,
1049                                               const int32_t min_dy,
1050                                               const int32_t max_dy,
1051                                               const int32_t iEdgedWidth,
1052                                               const int32_t iDiamondSize,
1053                                               const int32_t iFcode,
1054                                               const int32_t iQuant,
1055                                               int iDirection)
1056    {
1057    
1058          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )          int32_t iSAD;
                 iFound=2;  
1059    
1060  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
    Otherwise select large Diamond Search.  
 */  
1061    
1062          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )          if (iDirection) {
1063                  iDiamondSize=1; // halfpel!                  CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1064          else                  CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1065                  iDiamondSize=2; // halfpel!                  CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1066                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1067            } else {
1068                    int bDirection = 1 + 2 + 4 + 8;
1069    
1070                    do {
1071                            iDirection = 0;
1072                            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)
1073                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1074    
1075                            if (bDirection & 2)
1076                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1077    
1078                            if (bDirection & 4)
1079                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1080    
1081                            if (bDirection & 8)
1082                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1083    
1084                            /* now we're doing diagonal checks near our candidate */
1085    
1086                            if (iDirection)         //checking if anything found
1087                            {
1088                                    bDirection = iDirection;
1089                                    iDirection = 0;
1090                                    start_x = currMV->x;
1091                                    start_y = currMV->y;
1092                                    if (bDirection & 3)     //our candidate is left or right
1093                                    {
1094                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1095                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1096                                    } else                  // what remains here is up or down
1097                                    {
1098                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1099                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1100                                    }
1101    
1102                                    if (iDirection) {
1103                                            bDirection += iDirection;
1104                                            start_x = currMV->x;
1105                                            start_y = currMV->y;
1106                                    }
1107                            } else                          //about to quit, eh? not so fast....
1108                            {
1109                                    switch (bDirection) {
1110                                    case 2:
1111                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1112                                                                                            start_y - iDiamondSize, 2 + 4);
1113                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1114                                                                                            start_y + iDiamondSize, 2 + 8);
1115                                            break;
1116                                    case 1:
1117                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1118                                                                                            start_y - iDiamondSize, 1 + 4);
1119                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1120                                                                                            start_y + iDiamondSize, 1 + 8);
1121                                            break;
1122                                    case 2 + 4:
1123                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1124                                                                                            start_y - iDiamondSize, 1 + 4);
1125                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1126                                                                                            start_y - iDiamondSize, 2 + 4);
1127                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1128                                                                                            start_y + iDiamondSize, 2 + 8);
1129                                            break;
1130                                    case 4:
1131                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1132                                                                                            start_y - iDiamondSize, 2 + 4);
1133                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1134                                                                                            start_y - iDiamondSize, 1 + 4);
1135                                            break;
1136                                    case 8:
1137                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1138                                                                                            start_y + iDiamondSize, 2 + 8);
1139                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1140                                                                                            start_y + iDiamondSize, 1 + 8);
1141                                            break;
1142                                    case 1 + 4:
1143                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1144                                                                                            start_y + iDiamondSize, 1 + 8);
1145                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1146                                                                                            start_y - iDiamondSize, 1 + 4);
1147                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1148                                                                                            start_y - iDiamondSize, 2 + 4);
1149                                            break;
1150                                    case 2 + 8:
1151                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1152                                                                                            start_y - iDiamondSize, 1 + 4);
1153                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1154                                                                                            start_y + iDiamondSize, 1 + 8);
1155                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1156                                                                                            start_y + iDiamondSize, 2 + 8);
1157                                            break;
1158                                    case 1 + 8:
1159                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1160                                                                                            start_y - iDiamondSize, 2 + 4);
1161                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1162                                                                                            start_y + iDiamondSize, 2 + 8);
1163                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1164                                                                                            start_y + iDiamondSize, 1 + 8);
1165                                            break;
1166                                    default:                //1+2+4+8 == we didn't find anything at all
1167                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1168                                                                                            start_y - iDiamondSize, 1 + 4);
1169                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1170                                                                                            start_y + iDiamondSize, 1 + 8);
1171                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1172                                                                                            start_y - iDiamondSize, 2 + 4);
1173                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1174                                                                                            start_y + iDiamondSize, 2 + 8);
1175                                            break;
1176                                    }
1177                                    if (!(iDirection))
1178                                            break;          //ok, the end. really
1179                                    else {
1180                                            bDirection = iDirection;
1181                                            start_x = currMV->x;
1182                                            start_y = currMV->y;
1183                                    }
1184                            }
1185                    }
1186                    while (1);                              //forever
1187            }
1188            return iMinSAD;
1189    }
1190    
1191          if (!(MotionFlags & PMV_HALFPELDIAMOND16) )  
1192                  iDiamondSize*=2;  int32_t
1193    Full8_MainSearch(const uint8_t * const pRef,
1194                                     const uint8_t * const pRefH,
1195                                     const uint8_t * const pRefV,
1196                                     const uint8_t * const pRefHV,
1197                                     const uint8_t * const cur,
1198                                     const int x,
1199                                     const int y,
1200                               const int start_x,
1201                               const int start_y,
1202                               int iMinSAD,
1203                               VECTOR * const currMV,
1204                               const int center_x,
1205                               const int center_y,
1206                                     const int32_t min_dx,
1207                                     const int32_t max_dx,
1208                                     const int32_t min_dy,
1209                                     const int32_t max_dy,
1210                                     const int32_t iEdgedWidth,
1211                                     const int32_t iDiamondSize,
1212                                     const int32_t iFcode,
1213                                     const int32_t iQuant,
1214                                     int iFound)
1215    {
1216            int32_t iSAD;
1217            int32_t dx, dy;
1218            VECTOR backupMV;
1219    
1220            backupMV.x = start_x;
1221            backupMV.y = start_y;
1222    
1223            for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1224                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
1225                            NOCHECK_MV8_CANDIDATE(dx, dy);
1226    
1227            return iMinSAD;
1228    }
1229    
1230    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1231    
1232    int32_t
1233    Halfpel16_Refine(const uint8_t * const pRef,
1234                                     const uint8_t * const pRefH,
1235                                     const uint8_t * const pRefV,
1236                                     const uint8_t * const pRefHV,
1237                                     const uint8_t * const cur,
1238                                     const int x,
1239                                     const int y,
1240                                     VECTOR * const currMV,
1241                                     int32_t iMinSAD,
1242                               const int center_x,
1243                               const int center_y,
1244                                     const int32_t min_dx,
1245                                     const int32_t max_dx,
1246                                     const int32_t min_dy,
1247                                     const int32_t max_dy,
1248                                     const int32_t iFcode,
1249                                     const int32_t iQuant,
1250                                     const int32_t iEdgedWidth)
1251    {
1252    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1253    
1254            int32_t iSAD;
1255            VECTOR backupMV = *currMV;
1256    
1257            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1258            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y - 1);
1259            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1260            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y);
1261            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y);
1262            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1263            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y + 1);
1264            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1265    
1266            return iMinSAD;
1267    }
1268    
1269    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1270    
1271    
1272    
1273    int32_t
1274    PMVfastSearch16(const uint8_t * const pRef,
1275                                    const uint8_t * const pRefH,
1276                                    const uint8_t * const pRefV,
1277                                    const uint8_t * const pRefHV,
1278                                    const IMAGE * const pCur,
1279                                    const int x,
1280                                    const int y,
1281                                    const int start_x,
1282                                    const int start_y,
1283                                    const int center_x,
1284                                    const int center_y,
1285                                    const uint32_t MotionFlags,
1286                                    const uint32_t iQuant,
1287                                    const uint32_t iFcode,
1288                                    const MBParam * const pParam,
1289                                    const MACROBLOCK * const pMBs,
1290                                    const MACROBLOCK * const prevMBs,
1291                                    VECTOR * const currMV,
1292                                    VECTOR * const currPMV)
1293    {
1294            const uint32_t iWcount = pParam->mb_width;
1295            const int32_t iWidth = pParam->width;
1296            const int32_t iHeight = pParam->height;
1297            const int32_t iEdgedWidth = pParam->edged_width;
1298    
1299            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
1300    
1301            int32_t iDiamondSize;
1302    
1303            int32_t min_dx;
1304            int32_t max_dx;
1305            int32_t min_dy;
1306            int32_t max_dy;
1307    
1308            int32_t iFound;
1309    
1310            VECTOR newMV;
1311            VECTOR backupMV;                        /* just for PMVFAST */
1312    
1313            VECTOR pmv[4];
1314            int32_t psad[4];
1315    
1316            MainSearch16FuncPtr MainSearchPtr;
1317    
1318            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1319    
1320            int32_t threshA, threshB;
1321            int32_t bPredEq;
1322            int32_t iMinSAD, iSAD;
1323    
1324    /* Get maximum range */
1325            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1326                              iFcode);
1327    
1328    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1329    
1330            if (!(MotionFlags & PMV_HALFPEL16)) {
1331                    min_dx = EVEN(min_dx);
1332                    max_dx = EVEN(max_dx);
1333                    min_dy = EVEN(min_dy);
1334                    max_dy = EVEN(max_dy);
1335            }
1336    
1337            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1338            //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1339            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1340    
1341            if ((x == 0) && (y == 0)) {
1342                    threshA = 512;
1343                    threshB = 1024;
1344            } else {
1345                    threshA = psad[0];
1346                    threshB = threshA + 256;
1347                    if (threshA < 512)
1348                            threshA = 512;
1349                    if (threshA > 1024)
1350                            threshA = 1024;
1351                    if (threshB > 1792)
1352                            threshB = 1792;
1353            }
1354    
1355            iFound = 0;
1356    
1357  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1358     MinSAD=SAD     MinSAD=SAD
# Line 696  Line 1361 
1361     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1362  */  */
1363    
1364            currMV->x = start_x;
1365            currMV->y = start_y;
1366    
1367  // 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! */  
1368                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1369                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1370          }          }
1371    
1372          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1373                  currMV->x=max_dx;                  currMV->x=max_dx;
1374          }          }
1375          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1376                  currMV->x=min_dx;                  currMV->x=min_dx;
1377          }          }
1378          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1379                  currMV->y=max_dy;                  currMV->y=max_dy;
1380          }          }
1381          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1382                  currMV->y=min_dy;                  currMV->y=min_dy;
1383          }          }
1384    
1385          iMinSAD = sad16( cur,          iMinSAD =
1386                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1387                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1388          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1389            iMinSAD +=
1390          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1391          {                                            (uint8_t) iFcode, iQuant);
1392    
1393            if ((iMinSAD < 256) ||
1394                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1395                     ((int32_t) iMinSAD < prevMB->sad16))) {
1396                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1397                    {
1398                            if (!MVzero(*currMV)) {
1399                                    iMinSAD += MV16_00_BIAS;
1400                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1401                                    iMinSAD -= MV16_00_BIAS;
1402                            }
1403                    }
1404    
1405                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1406                          goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1407                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1408                          goto step10;                          goto PMVfast16_Terminate_with_Refine;
1409          }          }
1410    
1411    
1412    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1413       vector of the median.
1414       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1415    */
1416    
1417            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1418                    iFound = 2;
1419    
1420    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1421       Otherwise select large Diamond Search.
1422    */
1423    
1424            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1425                    iDiamondSize = 1;               // halfpel!
1426            else
1427                    iDiamondSize = 2;               // halfpel!
1428    
1429            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1430                    iDiamondSize *= 2;
1431    
1432  /*  /*
1433     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.
1434     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1435     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1436     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1437  */  */
1438    
1439  // (0,0) is always possible  // (0,0) is always possible
1440    
1441            if (!MVzero(pmv[0]))
1442          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1443    
1444  // previous frame MV is always possible  // previous frame MV is always possible
1445          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
1446            if (!MVzero(prevMB->mvs[0]))
1447                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1448                            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
1449    
1450  // left neighbour, if allowed  // left neighbour, if allowed
1451          if (x != 0)  
1452          {          if (!MVzero(pmv[1]))
1453                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1454                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1455                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1456                                            pmv[1].x = EVEN(pmv[1].x);
1457                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1458                  }                  }
1459    
1460                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1461          }          }
   
1462  // top neighbour, if allowed  // top neighbour, if allowed
1463          if (y != 0)          if (!MVzero(pmv[2]))
1464          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1465                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1466                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1467                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1468                                                    pmv[2].x = EVEN(pmv[2].x);
1469                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1470                  }                  }
1471                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1472    
1473  // top right neighbour, if allowed  // top right neighbour, if allowed
1474                  if (x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1475                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1476                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1477                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1478                                                                            if (!MVequal(pmv[3], pmv[2])) {
1479                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1480                                                                                            pmv[3].x = EVEN(pmv[3].x);
1481                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1482                          }                          }
1483                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1484                                                                                                                             pmv[3].y);
1485                  }                  }
1486          }          }
1487    
1488            if ((MVzero(*currMV)) &&
1489                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1490                    iMinSAD -= MV16_00_BIAS;
1491    
1492    
1493  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1494     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.
1495  */  */
1496    
1497          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1498          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1499                     ((int32_t) iMinSAD < prevMB->sad16))) {
1500                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1501                          goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1502                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1503                          goto step10;                          goto PMVfast16_Terminate_with_Refine;
1504          }          }
1505    
1506    
# Line 804  Line 1514 
1514     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1515  */  */
1516    
1517            if (MotionFlags & PMV_USESQUARES16)
1518                    MainSearchPtr = Square16_MainSearch;
1519            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1520                    MainSearchPtr = AdvDiamond16_MainSearch;
1521            else
1522                    MainSearchPtr = Diamond16_MainSearch;
1523    
1524          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1525    
1526    
1527  /* 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 */
1528          iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1529                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1530                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1531                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1532                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1533                                                      iQuant, iFound);
1534    
1535          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1536                  *currMV = newMV;                  *currMV = newMV;
1537                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1538          }          }
1539    
1540          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1541  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1542    
1543                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1544                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1545                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1546                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1547                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1548                                                                      iDiamondSize, iFcode, iQuant, iFound);
1549    
1550                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1551                          *currMV = newMV;                          *currMV = newMV;
1552                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1553                  }                  }
1554                  }                  }
1555    
1556                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1557                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1558                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1559                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1560                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1561                                                                      iEdgedWidth, iDiamondSize, iFcode,
1562                                                                      iQuant, iFound);
1563    
1564                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1565                          *currMV = newMV;                          *currMV = newMV;
1566                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1567                  }                  }
# Line 853  Line 1572 
1572     Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.     Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
1573  */  */
1574    
1575   step10:    PMVfast16_Terminate_with_Refine:
1576          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1577                  iMinSAD = PMVfastSearch16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1578                                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1579                                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1580                                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1581    
1582   step10b:    PMVfast16_Terminate_without_Refine:
1583          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1584          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1585          return iMinSAD;          return iMinSAD;
1586  }  }
1587    
# Line 871  Line 1590 
1590    
1591    
1592    
1593  int32_t PMVfastSearch8_MainSearch(  int32_t
1594          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1595          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1596          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1597          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1598          const uint8_t * const cur,          const uint8_t * const cur,
1599          const int x, const int y,                                          const int x,
1600          int32_t startx, int32_t starty,                                          const int y,
1601                                            int32_t start_x,
1602                                            int32_t start_y,
1603          int32_t iMinSAD,          int32_t iMinSAD,
1604          VECTOR * const currMV,          VECTOR * const currMV,
1605          const VECTOR * const pmv,                                     const int center_x,
1606          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
1607          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1608                                            const int32_t max_dx,
1609                                            const int32_t min_dy,
1610                                            const int32_t max_dy,
1611          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1612          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1613          const int32_t iFcode,          const int32_t iFcode,
# Line 893  Line 1617 
1617  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1618    
1619          int32_t iDirection=0;          int32_t iDirection=0;
1620            int32_t iDirectionBackup;
1621          int32_t iSAD;          int32_t iSAD;
1622          VECTOR backupMV;          VECTOR backupMV;
1623          backupMV.x = startx;  
1624          backupMV.y = starty;          backupMV.x = start_x;
1625            backupMV.y = start_y;
1626    
1627  /* 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 */
1628    
# Line 905  Line 1631 
1631          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1632          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1633    
1634          if (iDirection)          if (iDirection) {
1635                  while (!iFound)                  while (!iFound) {
                 {  
1636                          iFound = 1;                          iFound = 1;
1637                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1638                            iDirectionBackup = iDirection;
1639    
1640                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1641                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1642                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1643                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1644                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1645                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1646                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1647                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1648                                                                                      backupMV.y - iDiamondSize, 3);
1649                            if (iDirectionBackup != 3)
1650                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1651                                                                                      backupMV.y + iDiamondSize, 4);
1652                  }                  }
1653          else          } else {
1654                    currMV->x = start_x;
1655                    currMV->y = start_y;
1656            }
1657            return iMinSAD;
1658    }
1659    
1660    
1661    
1662    
1663    int32_t
1664    Square8_MainSearch(const uint8_t * const pRef,
1665                                            const uint8_t * const pRefH,
1666                                            const uint8_t * const pRefV,
1667                                            const uint8_t * const pRefHV,
1668                                            const uint8_t * const cur,
1669                                            const int x,
1670                                            const int y,
1671                                            int32_t start_x,
1672                                            int32_t start_y,
1673                                            int32_t iMinSAD,
1674                                            VECTOR * const currMV,
1675                                       const int center_x,
1676                                       const int center_y,
1677                                            const int32_t min_dx,
1678                                            const int32_t max_dx,
1679                                            const int32_t min_dy,
1680                                            const int32_t max_dy,
1681                                            const int32_t iEdgedWidth,
1682                                            const int32_t iDiamondSize,
1683                                            const int32_t iFcode,
1684                                            const int32_t iQuant,
1685                                            int iFound)
1686          {          {
1687                  currMV->x = startx;  /* Do a square search around given starting point, return SAD of best */
1688                  currMV->y = starty;  
1689            int32_t iDirection = 0;
1690            int32_t iSAD;
1691            VECTOR backupMV;
1692    
1693            backupMV.x = start_x;
1694            backupMV.y = start_y;
1695    
1696    /* It's one search with full square pattern, and new parts for all following diamonds */
1697    
1698    /*   new direction are extra, so 1-4 is normal diamond
1699          537
1700          1*2
1701          648
1702    */
1703    
1704            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1705            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1706            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1707            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1708    
1709            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1710                                                             backupMV.y - iDiamondSize, 5);
1711            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1712                                                             backupMV.y + iDiamondSize, 6);
1713            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1714                                                             backupMV.y - iDiamondSize, 7);
1715            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1716                                                             backupMV.y + iDiamondSize, 8);
1717    
1718    
1719            if (iDirection) {
1720                    while (!iFound) {
1721                            iFound = 1;
1722                            backupMV = *currMV;
1723    
1724                            switch (iDirection) {
1725                            case 1:
1726                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1727                                                                                       backupMV.y, 1);
1728                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1729                                                                                     backupMV.y - iDiamondSize, 5);
1730                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1731                                                                                     backupMV.y - iDiamondSize, 7);
1732                                    break;
1733                            case 2:
1734                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1735                                                                                     2);
1736                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1737                                                                                     backupMV.y + iDiamondSize, 6);
1738                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1739                                                                                     backupMV.y + iDiamondSize, 8);
1740                                    break;
1741    
1742                            case 3:
1743                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1744                                                                                     4);
1745                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1746                                                                                     backupMV.y - iDiamondSize, 7);
1747                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1748                                                                                     backupMV.y + iDiamondSize, 8);
1749                                    break;
1750    
1751                            case 4:
1752                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1753                                                                                     3);
1754                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1755                                                                                     backupMV.y - iDiamondSize, 5);
1756                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1757                                                                                     backupMV.y + iDiamondSize, 6);
1758                                    break;
1759    
1760                            case 5:
1761                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1762                                                                                     1);
1763                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1764                                                                                     3);
1765                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1766                                                                                     backupMV.y - iDiamondSize, 5);
1767                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1768                                                                                     backupMV.y + iDiamondSize, 6);
1769                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1770                                                                                     backupMV.y - iDiamondSize, 7);
1771                                    break;
1772    
1773                            case 6:
1774                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1775                                                                                     2);
1776                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1777                                                                                     3);
1778    
1779                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1780                                                                                     backupMV.y - iDiamondSize, 5);
1781                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1782                                                                                     backupMV.y + iDiamondSize, 6);
1783                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1784                                                                                     backupMV.y + iDiamondSize, 8);
1785    
1786                                    break;
1787    
1788                            case 7:
1789                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1790                                                                                       backupMV.y, 1);
1791                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1792                                                                                     4);
1793                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1794                                                                                     backupMV.y - iDiamondSize, 5);
1795                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1796                                                                                     backupMV.y - iDiamondSize, 7);
1797                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1798                                                                                     backupMV.y + iDiamondSize, 8);
1799                                    break;
1800    
1801                            case 8:
1802                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1803                                                                                     2);
1804                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1805                                                                                     4);
1806                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1807                                                                                     backupMV.y + iDiamondSize, 6);
1808                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1809                                                                                     backupMV.y - iDiamondSize, 7);
1810                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1811                                                                                     backupMV.y + iDiamondSize, 8);
1812                                    break;
1813                            default:
1814                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1815                                                                                     1);
1816                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1817                                                                                     2);
1818                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1819                                                                                     3);
1820                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1821                                                                                     4);
1822    
1823                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1824                                                                                     backupMV.y - iDiamondSize, 5);
1825                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1826                                                                                     backupMV.y + iDiamondSize, 6);
1827                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1828                                                                                     backupMV.y - iDiamondSize, 7);
1829                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1830                                                                                     backupMV.y + iDiamondSize, 8);
1831                                    break;
1832                            }
1833                    }
1834            } else {
1835                    currMV->x = start_x;
1836                    currMV->y = start_y;
1837          }          }
1838          return iMinSAD;          return iMinSAD;
1839  }  }
1840    
1841  int32_t PMVfastSearch8_Refine(  
1842          const uint8_t * const pRef,  
1843    
1844    
1845    int32_t
1846    Halfpel8_Refine_c(const uint8_t * const pRef,
1847          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1848          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1849          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1850          const uint8_t * const cur,          const uint8_t * const cur,
1851          const int x, const int y,                                  const int x,
1852                                    const int y,
1853          VECTOR * const currMV,          VECTOR * const currMV,
1854          int32_t iMinSAD,          int32_t iMinSAD,
1855          const VECTOR * const pmv,                             const int center_x,
1856          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1857          const int32_t min_dy, const int32_t max_dy,                                  const int32_t min_dx,
1858                                    const int32_t max_dx,
1859                                    const int32_t min_dy,
1860                                    const int32_t max_dy,
1861          const int32_t iFcode,          const int32_t iFcode,
1862          const int32_t iQuant,          const int32_t iQuant,
1863          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 964  Line 1882 
1882    
1883  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1884    
1885  int32_t PMVfastSearch8(  int32_t
1886          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1887          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1888          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1889          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1890          const IMAGE * const pCur,          const IMAGE * const pCur,
1891          const int x, const int y,                             const int x,
1892          const int start_x, int start_y,                             const int y,
1893                               const int start_x,
1894                               const int start_y,
1895                                    const int center_x,
1896                                    const int center_y,
1897          const uint32_t MotionFlags,          const uint32_t MotionFlags,
1898          MBParam * const pParam,                             const uint32_t iQuant,
1899          MACROBLOCK * const pMBs,                             const uint32_t iFcode,
1900                               const MBParam * const pParam,
1901                               const MACROBLOCK * const pMBs,
1902                               const MACROBLOCK * const prevMBs,
1903          VECTOR * const currMV,          VECTOR * const currMV,
1904          VECTOR * const currPMV)          VECTOR * const currPMV)
1905  {  {
1906          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
   
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
1907          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1908          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1909          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 999  Line 1921 
1921          int32_t psad[4];          int32_t psad[4];
1922          VECTOR newMV;          VECTOR newMV;
1923          VECTOR backupMV;          VECTOR backupMV;
1924            VECTOR startMV;
1925    
1926          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1927            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
1928    
1929          static int32_t threshA,threshB;           int32_t threshA, threshB;
1930          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1931          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1932    
1933          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1934    
1935  /* Get maximum range */          MainSearch8FuncPtr MainSearchPtr;
         get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                   x, y, 8, iWidth, iHeight, iFcode);  
1936    
1937  /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */          /* Init variables */
1938            startMV.x = start_x;
1939            startMV.y = start_y;
1940    
1941          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          /* Get maximum range */
1942          { min_dx = EVEN(min_dx);          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
1943                              iFcode);
1944    
1945            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
1946                    min_dx = EVEN(min_dx);
1947          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1948          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1949          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1950          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
1951    
1952          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1953            //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
1954            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
1955    
1956          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1957                  threshA =  512/4;                  threshA =  512/4;
1958                  threshB = 1024/4;                  threshB = 1024/4;
1959    
1960          }          } else {
1961          else                  threshA = psad[0] / 4;  /* good estimate? */
         {  
                 threshA = psad[0]/4;                    /* good estimate */  
1962                  threshB = threshA+256/4;                  threshB = threshA+256/4;
1963                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
1964                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
1965                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
1966                            threshA = 1024 / 4;
1967                    if (threshB > 1792 / 4)
1968                            threshB = 1792 / 4;
1969          }          }
1970    
1971          iFound=0;          iFound=0;
1972    
1973  /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  /* Step 4: Calculate SAD around the Median prediction.
1974       MinSAD=SAD
1975       If Motion Vector equal to Previous frame motion vector
1976       and MinSAD<PrevFrmSAD goto Step 10.
1977       If SAD<=256 goto Step 10.
1978    */
1979    
1980    
1981    // Prepare for main loop
1982    
1983      if (MotionFlags & PMV_USESQUARES8)
1984          MainSearchPtr = Square8_MainSearch;
1985      else
1986    
1987            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1988                    MainSearchPtr = AdvDiamond8_MainSearch;
1989            else
1990                    MainSearchPtr = Diamond8_MainSearch;
1991    
1992    
1993            *currMV = startMV;
1994    
1995            iMinSAD =
1996                    sad8(cur,
1997                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
1998                                                    iEdgedWidth), iEdgedWidth);
1999            iMinSAD +=
2000                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2001                                             (uint8_t) iFcode, iQuant);
2002    
2003            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
2004                                                                    && ((int32_t) iMinSAD <
2005                                                                            prevMB->sad8[iSubBlock]))) {
2006                    if (MotionFlags & PMV_QUICKSTOP16)
2007                            goto PMVfast8_Terminate_without_Refine;
2008                    if (MotionFlags & PMV_EARLYSTOP16)
2009                            goto PMVfast8_Terminate_with_Refine;
2010            }
2011    
2012    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2013     vector of the median.     vector of the median.
2014     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2015  */  */
2016    
2017          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )          if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
2018                  iFound=2;                  iFound=2;
2019    
2020  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2021     Otherwise select large Diamond Search.     Otherwise select large Diamond Search.
2022  */  */
2023    
2024          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )          if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
2025                  iDiamondSize=1; // 1 halfpel!                  iDiamondSize=1; // 1 halfpel!
2026          else          else
2027                  iDiamondSize=2; // 2 halfpel = 1 full pixel!                  iDiamondSize=2; // 2 halfpel = 1 full pixel!
# Line 1061  Line 2029 
2029          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
2030                  iDiamondSize*=2;                  iDiamondSize*=2;
2031    
 /* Step 4: Calculate SAD around the Median prediction.  
    MinSAD=SAD  
    If Motion Vector equal to Previous frame motion vector  
    and MinSAD<PrevFrmSAD goto Step 10.  
    If SAD<=256 goto Step 10.  
 */  
   
   
 // Prepare for main loop  
   
         currMV->x=start_x;              /* start with mv16 */  
         currMV->y=start_y;  
   
         iMinSAD = sad8( cur,  
                         get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),  
                         iEdgedWidth);  
         iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;  
   
         if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )  
         {  
                 if (MotionFlags & PMV_QUICKSTOP8)  
                         goto step10_8b;  
                 if (MotionFlags & PMV_EARLYSTOP8)  
                         goto step10_8;  
         }  
2032    
2033  /*  /*
2034     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.
2035     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
2036     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
2037     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
2038  */  */
2039    
2040  // 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);  
2041    
2042  // (0,0) is always possible          if (!MVequal(pmv[0], startMV))
2043                    CHECK_MV8_CANDIDATE(center_x, center_y);
2044    
2045    // (0,0) if needed
2046            if (!MVzero(pmv[0]))
2047                    if (!MVzero(startMV))
2048          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2049    
2050  // previous frame MV is always possible  // previous frame MV if needed
2051          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
2052                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
2053                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
2054                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
2055                                                                            prevMB->mvs[iSubBlock].y);
2056    
2057            if ((iMinSAD <= threshA) ||
2058                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2059                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2060                    if (MotionFlags & PMV_QUICKSTOP16)
2061                            goto PMVfast8_Terminate_without_Refine;
2062                    if (MotionFlags & PMV_EARLYSTOP16)
2063                            goto PMVfast8_Terminate_with_Refine;
2064            }
2065    
2066  // left neighbour, if allowed  // left neighbour, if allowed and needed
2067          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
2068          {                  if (!MVequal(pmv[1], startMV))
2069                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
2070                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
2071                                            if (!(MotionFlags & PMV_HALFPEL8)) {
2072                                                    pmv[1].x = EVEN(pmv[1].x);
2073                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
2074                  }                  }
2075                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2076          }          }
2077    // top neighbour, if allowed and needed
2078  // top neighbour, if allowed          if (!MVzero(pmv[2]))
2079          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
2080          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
2081                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
2082                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
2083                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
2084                                                            pmv[2].x = EVEN(pmv[2].x);
2085                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
2086                  }                  }
2087                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2088    
2089  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
2090                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
2091                  {                                                          if (!MVequal(pmv[3], startMV))
2092                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
2093                          {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
2094                                                                                    if (!MVequal(pmv[3], pmv[1]))
2095                                                                                            if (!MVequal(pmv[3], pmv[2])) {
2096                                                                                                    if (!
2097                                                                                                            (MotionFlags &
2098                                                                                                             PMV_HALFPEL8)) {
2099                                                                                                            pmv[3].x = EVEN(pmv[3].x);
2100                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
2101                          }                          }
2102                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
2103                                                                                                                                            pmv[3].y);
2104                  }                  }
2105          }          }
2106    
2107            if ((MVzero(*currMV)) &&
2108                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2109                    iMinSAD -= MV8_00_BIAS;
2110    
2111    
2112  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
2113     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.
2114  */  */
2115    
2116          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2117          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2118                  if (MotionFlags & PMV_QUICKSTOP8)                   ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2119                          goto step10_8b;                  if (MotionFlags & PMV_QUICKSTOP16)
2120                  if (MotionFlags & PMV_EARLYSTOP8)                          goto PMVfast8_Terminate_without_Refine;
2121                          goto step10_8;                  if (MotionFlags & PMV_EARLYSTOP16)
2122                            goto PMVfast8_Terminate_with_Refine;
2123          }          }
2124    
2125  /************ (Diamond Search)  **************/  /************ (Diamond Search)  **************/
# Line 1158  Line 2135 
2135          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2136    
2137  /* 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 */
2138          iSAD = PMVfastSearch8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2139                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2140                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2141                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2142                                                      iQuant, iFound);
2143    
2144          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2145                  *currMV = newMV;                  *currMV = newMV;
2146                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2147          }          }
2148    
2149          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2150  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
2151    
2152                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2153                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2154                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2155                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2156                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2157                                                                      iDiamondSize, iFcode, iQuant, iFound);
2158    
2159                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2160                          *currMV = newMV;                          *currMV = newMV;
2161                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2162                  }                  }
2163                  }                  }
2164    
2165                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2166                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2167                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2168                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2169                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2170                                                                      iQuant, iFound);
2171    
2172                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2173                          *currMV = newMV;                          *currMV = newMV;
2174                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2175                  }                  }
# Line 1204  Line 2180 
2180     By performing an optional local half-pixel search, we can refine this result even further.     By performing an optional local half-pixel search, we can refine this result even further.
2181  */  */
2182    
2183   step10_8:    PMVfast8_Terminate_with_Refine:
2184          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2185                  iMinSAD = PMVfastSearch8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2186                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2187                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2188                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2189    
  step10_8b:  
2190    
2191          currPMV->x = currMV->x - pmv[0].x;    PMVfast8_Terminate_without_Refine:
2192          currPMV->y = currMV->y - pmv[0].y;          currPMV->x = currMV->x - center_x;
2193            currPMV->y = currMV->y - center_y;
2194    
2195          return iMinSAD;          return iMinSAD;
2196  }  }
2197    
2198    int32_t
2199    EPZSSearch16(const uint8_t * const pRef,
2200                             const uint8_t * const pRefH,
2201                             const uint8_t * const pRefV,
2202                             const uint8_t * const pRefHV,
2203                             const IMAGE * const pCur,
2204                             const int x,
2205                             const int y,
2206                            const int start_x,
2207                            const int start_y,
2208                            const int center_x,
2209                            const int center_y,
2210                             const uint32_t MotionFlags,
2211                             const uint32_t iQuant,
2212                             const uint32_t iFcode,
2213                             const MBParam * const pParam,
2214                             const MACROBLOCK * const pMBs,
2215                             const MACROBLOCK * const prevMBs,
2216                             VECTOR * const currMV,
2217                             VECTOR * const currPMV)
2218    {
2219            const uint32_t iWcount = pParam->mb_width;
2220            const uint32_t iHcount = pParam->mb_height;
2221    
2222            const int32_t iWidth = pParam->width;
2223            const int32_t iHeight = pParam->height;
2224            const int32_t iEdgedWidth = pParam->edged_width;
2225    
2226            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2227    
2228            int32_t min_dx;
2229            int32_t max_dx;
2230            int32_t min_dy;
2231            int32_t max_dy;
2232    
2233            VECTOR newMV;
2234            VECTOR backupMV;
2235    
2236            VECTOR pmv[4];
2237            int32_t psad[8];
2238    
2239            static MACROBLOCK *oldMBs = NULL;
2240    
2241    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2242            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2243            MACROBLOCK *oldMB = NULL;
2244    
2245             int32_t thresh2;
2246            int32_t bPredEq;
2247            int32_t iMinSAD, iSAD = 9999;
2248    
2249            MainSearch16FuncPtr MainSearchPtr;
2250    
2251            if (oldMBs == NULL) {
2252                    oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2253    //      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2254            }
2255            oldMB = oldMBs + x + y * iWcount;
2256    
2257    /* Get maximum range */
2258            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2259                              iFcode);
2260    
2261            if (!(MotionFlags & PMV_HALFPEL16)) {
2262                    min_dx = EVEN(min_dx);
2263                    max_dx = EVEN(max_dx);
2264                    min_dy = EVEN(min_dy);
2265                    max_dy = EVEN(max_dy);
2266            }
2267            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2268            //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2269            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2270    
2271    /* Step 4: Calculate SAD around the Median prediction.
2272            MinSAD=SAD
2273            If Motion Vector equal to Previous frame motion vector
2274                    and MinSAD<PrevFrmSAD goto Step 10.
2275            If SAD<=256 goto Step 10.
2276    */
2277    
2278    // Prepare for main loop
2279    
2280            currMV->x = start_x;
2281            currMV->y = start_y;
2282    
2283            if (!(MotionFlags & PMV_HALFPEL16)) {
2284                    currMV->x = EVEN(currMV->x);
2285                    currMV->y = EVEN(currMV->y);
2286            }
2287    
2288            if (currMV->x > max_dx)
2289                    currMV->x = max_dx;
2290            if (currMV->x < min_dx)
2291                    currMV->x = min_dx;
2292            if (currMV->y > max_dy)
2293                    currMV->y = max_dy;
2294            if (currMV->y < min_dy)
2295                    currMV->y = min_dy;
2296    
2297    /***************** This is predictor SET A: only median prediction ******************/
2298    
2299            iMinSAD =
2300                    sad16(cur,
2301                              get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2302                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2303            iMinSAD +=
2304                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2305                                              (uint8_t) iFcode, iQuant);
2306    
2307    // thresh1 is fixed to 256
2308            if ((iMinSAD < 256) ||
2309                    ((MVequal(*currMV, prevMB->mvs[0])) &&
2310                     ((int32_t) iMinSAD < prevMB->sad16))) {
2311                    if (MotionFlags & PMV_QUICKSTOP16)
2312                            goto EPZS16_Terminate_without_Refine;
2313                    if (MotionFlags & PMV_EARLYSTOP16)
2314                            goto EPZS16_Terminate_with_Refine;
2315            }
2316    
2317    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2318    
2319    // previous frame MV
2320            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
2321    
2322    // set threshhold based on Min of Prediction and SAD of collocated block
2323    // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
2324    
2325            if ((x == 0) && (y == 0)) {
2326                    thresh2 = 512;
2327            } else {
2328    /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
2329    
2330                    thresh2 = MIN(psad[0], iSAD) * 6 / 5 + 128;
2331            }
2332    
2333    // MV=(0,0) is often a good choice
2334    
2335            CHECK_MV16_ZERO;
2336    
2337    
2338    // left neighbour, if allowed
2339            if (x != 0) {
2340                    if (!(MotionFlags & PMV_HALFPEL16)) {
2341                            pmv[1].x = EVEN(pmv[1].x);
2342                            pmv[1].y = EVEN(pmv[1].y);
2343                    }
2344                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2345            }
2346    // top neighbour, if allowed
2347            if (y != 0) {
2348                    if (!(MotionFlags & PMV_HALFPEL16)) {
2349                            pmv[2].x = EVEN(pmv[2].x);
2350                            pmv[2].y = EVEN(pmv[2].y);
2351                    }
2352                    CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2353    
2354    // top right neighbour, if allowed
2355                    if ((uint32_t) x != (iWcount - 1)) {
2356                            if (!(MotionFlags & PMV_HALFPEL16)) {
2357                                    pmv[3].x = EVEN(pmv[3].x);
2358                                    pmv[3].y = EVEN(pmv[3].y);
2359                            }
2360                            CHECK_MV16_CANDIDATE(pmv[3].x, pmv[3].y);
2361                    }
2362            }
2363    
2364    /* Terminate if MinSAD <= T_2
2365       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2366    */
2367    
2368            if ((iMinSAD <= thresh2)
2369                    || (MVequal(*currMV, prevMB->mvs[0]) &&
2370                            ((int32_t) iMinSAD <= prevMB->sad16))) {
2371                    if (MotionFlags & PMV_QUICKSTOP16)
2372                            goto EPZS16_Terminate_without_Refine;
2373                    if (MotionFlags & PMV_EARLYSTOP16)
2374                            goto EPZS16_Terminate_with_Refine;
2375            }
2376    
2377    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
2378    
2379            backupMV = prevMB->mvs[0];      // collocated MV
2380            backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2381            backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2382    
2383            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y);
2384    
2385    // left neighbour
2386            if (x != 0)
2387                    CHECK_MV16_CANDIDATE((prevMB - 1)->mvs[0].x, (prevMB - 1)->mvs[0].y);
2388    
2389    // top neighbour
2390            if (y != 0)
2391                    CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2392                                                             (prevMB - iWcount)->mvs[0].y);
2393    
2394    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2395    
2396            if ((uint32_t) x != iWcount - 1)
2397                    CHECK_MV16_CANDIDATE((prevMB + 1)->mvs[0].x, (prevMB + 1)->mvs[0].y);
2398    
2399    // bottom neighbour, dito
2400            if ((uint32_t) y != iHcount - 1)
2401                    CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2402                                                             (prevMB + iWcount)->mvs[0].y);
2403    
2404    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2405            if (iMinSAD <= thresh2) {
2406                    if (MotionFlags & PMV_QUICKSTOP16)
2407                            goto EPZS16_Terminate_without_Refine;
2408                    if (MotionFlags & PMV_EARLYSTOP16)
2409                            goto EPZS16_Terminate_with_Refine;
2410            }
2411    
2412    /************ (if Diamond Search)  **************/
2413    
2414            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2415    
2416            if (MotionFlags & PMV_USESQUARES16)
2417                    MainSearchPtr = Square16_MainSearch;
2418            else
2419             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2420                    MainSearchPtr = AdvDiamond16_MainSearch;
2421            else
2422                    MainSearchPtr = Diamond16_MainSearch;
2423    
2424    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2425    
2426            iSAD =
2427                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2428                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2429                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2430    
2431            if (iSAD < iMinSAD) {
2432                    *currMV = newMV;
2433                    iMinSAD = iSAD;
2434            }
2435    
2436    
2437            if (MotionFlags & PMV_EXTSEARCH16) {
2438    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2439    
2440                    if (!(MVequal(pmv[0], backupMV))) {
2441                            iSAD =
2442                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2443                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2444                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2445                                                                      2, iFcode, iQuant, 0);
2446                    }
2447    
2448                    if (iSAD < iMinSAD) {
2449                            *currMV = newMV;
2450                            iMinSAD = iSAD;
2451                    }
2452    
2453                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2454                            iSAD =
2455                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2456                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2457                                                                      max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2458    
2459                            if (iSAD < iMinSAD) {
2460                                    *currMV = newMV;
2461                                    iMinSAD = iSAD;
2462                            }
2463                    }
2464            }
2465    
2466    /***************        Choose best MV found     **************/
2467    
2468      EPZS16_Terminate_with_Refine:
2469            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2470                    iMinSAD =
2471                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2472                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2473                                                             iFcode, iQuant, iEdgedWidth);
2474    
2475      EPZS16_Terminate_without_Refine:
2476    
2477            *oldMB = *prevMB;
2478    
2479            currPMV->x = currMV->x - center_x;
2480            currPMV->y = currMV->y - center_y;
2481            return iMinSAD;
2482    }
2483    
2484    
2485    int32_t
2486    EPZSSearch8(const uint8_t * const pRef,
2487                            const uint8_t * const pRefH,
2488                            const uint8_t * const pRefV,
2489                            const uint8_t * const pRefHV,
2490                            const IMAGE * const pCur,
2491                            const int x,
2492                            const int y,
2493                            const int start_x,
2494                            const int start_y,
2495                            const int center_x,
2496                            const int center_y,
2497                            const uint32_t MotionFlags,
2498                            const uint32_t iQuant,
2499                            const uint32_t iFcode,
2500                            const MBParam * const pParam,
2501                            const MACROBLOCK * const pMBs,
2502                            const MACROBLOCK * const prevMBs,
2503                            VECTOR * const currMV,
2504                            VECTOR * const currPMV)
2505    {
2506    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
2507    
2508            const uint32_t iWcount = pParam->mb_width;
2509            const int32_t iWidth = pParam->width;
2510            const int32_t iHeight = pParam->height;
2511            const int32_t iEdgedWidth = pParam->edged_width;
2512    
2513            const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;
2514    
2515            int32_t iDiamondSize = 1;
2516    
2517            int32_t min_dx;
2518            int32_t max_dx;
2519            int32_t min_dy;
2520            int32_t max_dy;
2521    
2522            VECTOR newMV;
2523            VECTOR backupMV;
2524    
2525            VECTOR pmv[4];
2526            int32_t psad[8];
2527    
2528            const int32_t iSubBlock = ((y & 1) << 1) + (x & 1);
2529    
2530    //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2531            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2532    
2533            int32_t bPredEq;
2534            int32_t iMinSAD, iSAD = 9999;
2535    
2536            MainSearch8FuncPtr MainSearchPtr;
2537    
2538    /* Get maximum range */
2539            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2540                              iFcode);
2541    
2542    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2543    
2544            if (!(MotionFlags & PMV_HALFPEL8)) {
2545                    min_dx = EVEN(min_dx);
2546                    max_dx = EVEN(max_dx);
2547                    min_dy = EVEN(min_dy);
2548                    max_dy = EVEN(max_dy);
2549            }
2550            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2551            //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv[0].x, pmv[0].y, psad);
2552            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2553    
2554    
2555    /* Step 4: Calculate SAD around the Median prediction.
2556            MinSAD=SAD
2557            If Motion Vector equal to Previous frame motion vector
2558                    and MinSAD<PrevFrmSAD goto Step 10.
2559            If SAD<=256 goto Step 10.
2560    */
2561    
2562    // Prepare for main loop
2563    
2564    
2565            if (!(MotionFlags & PMV_HALFPEL8)) {
2566                    currMV->x = EVEN(currMV->x);
2567                    currMV->y = EVEN(currMV->y);
2568            }
2569    
2570            if (currMV->x > max_dx)
2571                    currMV->x = max_dx;
2572            if (currMV->x < min_dx)
2573                    currMV->x = min_dx;
2574            if (currMV->y > max_dy)
2575                    currMV->y = max_dy;
2576            if (currMV->y < min_dy)
2577                    currMV->y = min_dy;
2578    
2579    /***************** This is predictor SET A: only median prediction ******************/
2580    
2581    
2582            iMinSAD =
2583                    sad8(cur,
2584                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2585                                                    iEdgedWidth), iEdgedWidth);
2586            iMinSAD +=
2587                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2588                                             (uint8_t) iFcode, iQuant);
2589    
2590    
2591    // thresh1 is fixed to 256
2592            if (iMinSAD < 256 / 4) {
2593                    if (MotionFlags & PMV_QUICKSTOP8)
2594                            goto EPZS8_Terminate_without_Refine;
2595                    if (MotionFlags & PMV_EARLYSTOP8)
2596                            goto EPZS8_Terminate_with_Refine;
2597            }
2598    
2599    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2600    
2601    
2602    // MV=(0,0) is often a good choice
2603            CHECK_MV8_ZERO;
2604    
2605    // previous frame MV
2606            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2607    
2608    // left neighbour, if allowed
2609            if (psad[1] != MV_MAX_ERROR) {
2610                    if (!(MotionFlags & PMV_HALFPEL8)) {
2611                            pmv[1].x = EVEN(pmv[1].x);
2612                            pmv[1].y = EVEN(pmv[1].y);
2613                    }
2614                    CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2615            }
2616    // top neighbour, if allowed
2617            if (psad[2] != MV_MAX_ERROR) {
2618                    if (!(MotionFlags & PMV_HALFPEL8)) {
2619                            pmv[2].x = EVEN(pmv[2].x);
2620                            pmv[2].y = EVEN(pmv[2].y);
2621                    }
2622                    CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2623    
2624    // top right neighbour, if allowed
2625                    if (psad[3] != MV_MAX_ERROR) {
2626                            if (!(MotionFlags & PMV_HALFPEL8)) {
2627                                    pmv[3].x = EVEN(pmv[3].x);
2628                                    pmv[3].y = EVEN(pmv[3].y);
2629                            }
2630                            CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2631                    }
2632            }
2633    
2634    /*  // this bias is zero anyway, at the moment!
2635    
2636            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2637                    iMinSAD -= MV8_00_BIAS;
2638    
2639    */
2640    
2641    /* Terminate if MinSAD <= T_2
2642       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2643    */
2644    
2645            if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
2646                    if (MotionFlags & PMV_QUICKSTOP8)
2647                            goto EPZS8_Terminate_without_Refine;
2648                    if (MotionFlags & PMV_EARLYSTOP8)
2649                            goto EPZS8_Terminate_with_Refine;
2650            }
2651    
2652    /************ (Diamond Search)  **************/
2653    
2654            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2655    
2656            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2657                    iDiamondSize *= 2;
2658    
2659    /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2660    
2661    // there is no EPZS^2 for inter4v at the moment
2662    
2663      if (MotionFlags & PMV_USESQUARES8)
2664          MainSearchPtr = Square8_MainSearch;
2665      else
2666    
2667            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2668                    MainSearchPtr = AdvDiamond8_MainSearch;
2669            else
2670                    MainSearchPtr = Diamond8_MainSearch;
2671    
2672            iSAD =
2673                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2674                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2675                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2676                                                      iQuant, 0);
2677    
2678    
2679            if (iSAD < iMinSAD) {
2680                    *currMV = newMV;
2681                    iMinSAD = iSAD;
2682            }
2683    
2684            if (MotionFlags & PMV_EXTSEARCH8) {
2685    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2686    
2687                    if (!(MVequal(pmv[0], backupMV))) {
2688                            iSAD =
2689                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2690                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2691                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2692                                                                      iDiamondSize, iFcode, iQuant, 0);
2693    
2694                            if (iSAD < iMinSAD) {
2695                                    *currMV = newMV;
2696                                    iMinSAD = iSAD;
2697                            }
2698                    }
2699    
2700                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2701                            iSAD =
2702                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2703                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2704                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
2705                                                                      iQuant, 0);
2706    
2707                            if (iSAD < iMinSAD) {
2708                                    *currMV = newMV;
2709                                    iMinSAD = iSAD;
2710                            }
2711                    }
2712            }
2713    
2714    /***************        Choose best MV found     **************/
2715    
2716      EPZS8_Terminate_with_Refine:
2717            if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2718                    iMinSAD =
2719                            Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2720                                                            iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2721                                                            iFcode, iQuant, iEdgedWidth);
2722    
2723      EPZS8_Terminate_without_Refine:
2724    
2725            currPMV->x = currMV->x - center_x;
2726            currPMV->y = currMV->y - center_y;
2727            return iMinSAD;
2728    }
2729    
2730    
2731    
2732    int32_t
2733    PMVfastIntSearch16(const uint8_t * const pRef,
2734                                    const uint8_t * const pRefH,
2735                                    const uint8_t * const pRefV,
2736                                    const uint8_t * const pRefHV,
2737                                    const IMAGE * const pCur,
2738                                    const int x,
2739                                    const int y,
2740                            const int start_x,
2741                            const int start_y,
2742                            const int center_x,
2743                            const int center_y,
2744                                    const uint32_t MotionFlags,
2745                                    const uint32_t iQuant,
2746                                    const uint32_t iFcode,
2747                                    const MBParam * const pParam,
2748                                    const MACROBLOCK * const pMBs,
2749                                    const MACROBLOCK * const prevMBs,
2750                                    VECTOR * const currMV,
2751                                    VECTOR * const currPMV)
2752    {
2753            const uint32_t iWcount = pParam->mb_width;
2754            const int32_t iWidth = pParam->width;
2755            const int32_t iHeight = pParam->height;
2756            const int32_t iEdgedWidth = pParam->edged_width;
2757    
2758            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2759            const VECTOR zeroMV = { 0, 0 };
2760    
2761            int32_t iDiamondSize;
2762    
2763            int32_t min_dx;
2764            int32_t max_dx;
2765            int32_t min_dy;
2766            int32_t max_dy;
2767    
2768            int32_t iFound;
2769    
2770            VECTOR newMV;
2771            VECTOR backupMV;                        /* just for PMVFAST */
2772    
2773            VECTOR pmv[4];
2774            int32_t psad[4];
2775    
2776            MainSearch16FuncPtr MainSearchPtr;
2777    
2778            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2779            MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2780    
2781            int32_t threshA, threshB;
2782            int32_t bPredEq;
2783            int32_t iMinSAD, iSAD;
2784    
2785    
2786    /* Get maximum range */
2787            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2788                              iFcode);
2789    
2790    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2791    
2792            if ((x == 0) && (y == 0)) {
2793                    threshA = 512;
2794                    threshB = 1024;
2795    
2796                    bPredEq = 0;
2797                    psad[0] = psad[1] = psad[2] = psad[3] = 0;
2798                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2799    
2800            } else {
2801                    threshA = psad[0];
2802                    threshB = threshA + 256;
2803                    if (threshA < 512)
2804                            threshA = 512;
2805                    if (threshA > 1024)
2806                            threshA = 1024;
2807                    if (threshB > 1792)
2808                            threshB = 1792;
2809    
2810                    bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2811                    *currMV = pmv[0];                       /* current best := prediction */
2812            }
2813    
2814            iFound = 0;
2815    
2816    /* Step 4: Calculate SAD around the Median prediction.
2817       MinSAD=SAD
2818       If Motion Vector equal to Previous frame motion vector
2819       and MinSAD<PrevFrmSAD goto Step 10.
2820       If SAD<=256 goto Step 10.
2821    */
2822    
2823            if (currMV->x > max_dx) {
2824                    currMV->x = EVEN(max_dx);
2825            }
2826            if (currMV->x < min_dx) {
2827                    currMV->x = EVEN(min_dx);
2828            }
2829            if (currMV->y > max_dy) {
2830                    currMV->y = EVEN(max_dy);
2831            }
2832            if (currMV->y < min_dy) {
2833                    currMV->y = EVEN(min_dy);
2834            }
2835    
2836            iMinSAD =
2837                    sad16(cur,
2838                              get_iref_mv(pRef, x, y, 16, currMV,
2839                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2840            iMinSAD +=
2841                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2842                                              (uint8_t) iFcode, iQuant);
2843    
2844            if ((iMinSAD < 256) ||
2845                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2846                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2847                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
2848                    {
2849                            if (!MVzero(*currMV)) {
2850                                    iMinSAD += MV16_00_BIAS;
2851                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2852                                    iMinSAD -= MV16_00_BIAS;
2853                            }
2854                    }
2855    
2856                    if (MotionFlags & PMV_EARLYSTOP16)
2857                            goto PMVfastInt16_Terminate_with_Refine;
2858            }
2859    
2860    
2861    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2862       vector of the median.
2863       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2864    */
2865    
2866            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2867                    iFound = 2;
2868    
2869    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2870       Otherwise select large Diamond Search.
2871    */
2872    
2873            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2874                    iDiamondSize = 2;               // halfpel units!
2875            else
2876                    iDiamondSize = 4;               // halfpel units!
2877    
2878    /*
2879       Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2880       Also calculate (0,0) but do not subtract offset.
2881       Let MinSAD be the smallest SAD up to this point.
2882       If MV is (0,0) subtract offset.
2883    */
2884    
2885    // (0,0) is often a good choice
2886    
2887            if (!MVzero(pmv[0]))
2888                    CHECK_MV16_ZERO;
2889    
2890    // previous frame MV is always possible
2891    
2892            if (!MVzero(prevMB->i_mvs[0]))
2893                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2894                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2895    
2896    // left neighbour, if allowed
2897    
2898            if (!MVzero(pmv[1]))
2899                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2900                            if (!MVequal(pmv[1], pmv[0]))
2901                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2902    
2903    // top neighbour, if allowed
2904            if (!MVzero(pmv[2]))
2905                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
2906                            if (!MVequal(pmv[2], pmv[0]))
2907                                    if (!MVequal(pmv[2], pmv[1]))
2908                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2909    
2910    // top right neighbour, if allowed
2911                                            if (!MVzero(pmv[3]))
2912                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
2913                                                            if (!MVequal(pmv[3], pmv[0]))
2914                                                                    if (!MVequal(pmv[3], pmv[1]))
2915                                                                            if (!MVequal(pmv[3], pmv[2]))
2916                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
2917                                                                                                                             pmv[3].y);
2918    
2919            if ((MVzero(*currMV)) &&
2920                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2921                    iMinSAD -= MV16_00_BIAS;
2922    
2923    
2924    /* Step 6: If MinSAD <= thresa goto Step 10.
2925       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2926    */
2927    
2928            if ((iMinSAD <= threshA) ||
2929                    (MVequal(*currMV, prevMB->i_mvs[0]) &&
2930                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2931    
2932                    if (MotionFlags & PMV_EARLYSTOP16)
2933                            goto PMVfastInt16_Terminate_with_Refine;
2934            }
2935    
2936    
2937    /************ (Diamond Search)  **************/
2938    /*
2939       Step 7: Perform Diamond search, with either the small or large diamond.
2940       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
2941       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
2942       If center then goto step 10.
2943       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
2944       Refine by using small diamond and goto step 10.
2945    */
2946    
2947            if (MotionFlags & PMV_USESQUARES16)
2948                    MainSearchPtr = Square16_MainSearch;
2949            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2950                    MainSearchPtr = AdvDiamond16_MainSearch;
2951            else
2952                    MainSearchPtr = Diamond16_MainSearch;
2953    
2954            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2955    
2956    
2957    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2958            iSAD =
2959                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2960                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2961                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2962                                                      iQuant, iFound);
2963    
2964            if (iSAD < iMinSAD) {
2965                    *currMV = newMV;
2966                    iMinSAD = iSAD;
2967            }
2968    
2969            if (MotionFlags & PMV_EXTSEARCH16) {
2970    /* extended: search (up to) two more times: orignal prediction and (0,0) */
2971    
2972                    if (!(MVequal(pmv[0], backupMV))) {
2973                            iSAD =
2974                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2975                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2976                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2977                                                                      iDiamondSize, iFcode, iQuant, iFound);
2978    
2979                            if (iSAD < iMinSAD) {
2980                                    *currMV = newMV;
2981                                    iMinSAD = iSAD;
2982                            }
2983                    }
2984    
2985                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2986                            iSAD =
2987                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2988                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2989                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
2990                                                                      iQuant, iFound);
2991    
2992                            if (iSAD < iMinSAD) {
2993                                    *currMV = newMV;
2994                                    iMinSAD = iSAD;
2995                            }
2996                    }
2997            }
2998    
2999    /*
3000       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
3001    */
3002    
3003    PMVfastInt16_Terminate_with_Refine:
3004    
3005            pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
3006            pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
3007    
3008            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
3009                    iMinSAD =
3010                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
3011                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
3012                                                             iFcode, iQuant, iEdgedWidth);
3013    
3014            pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
3015    
3016    PMVfastInt16_Terminate_without_Refine:
3017            currPMV->x = currMV->x - center_x;
3018            currPMV->y = currMV->y - center_y;
3019            return iMinSAD;
3020    }
3021    
3022    
3023    
3024    /* ***********************************************************
3025            bvop motion estimation
3026    // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
3027    ***************************************************************/
3028    
3029    
3030    #define DIRECT_PENALTY 0
3031    #define DIRECT_UPPERLIMIT 256   // never use direct mode if SAD is larger than this
3032    
3033    void
3034    MotionEstimationBVOP(MBParam * const pParam,
3035                                             FRAMEINFO * const frame,
3036                                             const int32_t time_bp,
3037                                             const int32_t time_pp,
3038                                             // forward (past) reference
3039                                             const MACROBLOCK * const f_mbs,
3040                                             const IMAGE * const f_ref,
3041                                             const IMAGE * const f_refH,
3042                                             const IMAGE * const f_refV,
3043                                             const IMAGE * const f_refHV,
3044                                             // backward (future) reference
3045                                             const MACROBLOCK * const b_mbs,
3046                                             const IMAGE * const b_ref,
3047                                             const IMAGE * const b_refH,
3048                                             const IMAGE * const b_refV,
3049                                             const IMAGE * const b_refHV)
3050    {
3051            const int mb_width = pParam->mb_width;
3052            const int mb_height = pParam->mb_height;
3053            const int edged_width = pParam->edged_width;
3054    
3055            int i, j, k;
3056    
3057            static const VECTOR zeroMV={0,0};
3058    
3059            int f_sad16;    /* forward (as usual) search */
3060            int b_sad16;    /* backward (only in b-frames) search */
3061            int i_sad16;    /* interpolated (both direction, b-frames only) */
3062            int d_sad16;    /* direct mode (assume linear motion) */
3063    
3064            int best_sad;
3065    
3066            VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
3067            VECTOR pmv_dontcare;
3068    
3069            int f_count=0;
3070            int b_count=0;
3071            int i_count=0;
3072            int d_count=0;
3073            int s_count=0;
3074    
3075            const int64_t TRB = (int32_t)time_pp - (int32_t)time_bp;
3076        const int64_t TRD = (int32_t)time_pp;
3077    
3078            // fprintf(stderr,"TRB = %lld  TRD = %lld  time_bp =%d time_pp =%d\n\n",TRB,TRD,time_bp,time_pp);
3079            // note: i==horizontal, j==vertical
3080            for (j = 0; j < mb_height; j++) {
3081    
3082                    f_predMV = zeroMV;      /* prediction is reset at left boundary */
3083                    b_predMV = zeroMV;
3084    
3085                    for (i = 0; i < mb_width; i++) {
3086                            MACROBLOCK *mb = &frame->mbs[i + j * mb_width];
3087                            const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width];
3088                            const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width];
3089    
3090                            mb->deltamv=zeroMV;
3091    
3092    /* special case, if collocated block is SKIPed: encoding is forward(0,0)  */
3093    
3094    #ifndef _DISABLE_SKIP
3095                            if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
3096                                    b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {
3097                                    mb->mode = MODE_NOT_CODED;
3098                                    mb->mvs[0].x = 0;
3099                                    mb->mvs[0].y = 0;
3100                                    mb->b_mvs[0].x = 0;
3101                                    mb->b_mvs[0].y = 0;
3102                                    continue;
3103                            }
3104    #endif
3105    
3106                            d_sad16 = DIRECT_PENALTY;
3107    
3108                            if (b_mb->mode == MODE_INTER4V)
3109                            {
3110    
3111                            /* same method of scaling as in decoder.c, so we copy from there */
3112                        for (k = 0; k < 4; k++) {
3113    
3114                                            mb->directmv[k] = b_mb->mvs[k];
3115    
3116                                            mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3117                        mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3118                                                                                    ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3119                                                : mb->mvs[k].x - mb->directmv[k].x);
3120    
3121                        mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3122                            mb->b_mvs[k].y = (int32_t) ((mb->directmv[k].y == 0)
3123                                                                                    ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3124                                                : mb->mvs[k].y - mb->directmv[k].y);
3125    
3126                                            d_sad16 +=
3127                                                    sad8bi(frame->image.y + 2*(i+(k&1))*8 + 2*(j+(k>>1))*8*edged_width,
3128                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3129                                                                    2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->mvs[k], edged_width),
3130                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3131                                                                    2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->b_mvs[k], edged_width),
3132                                                      edged_width);
3133                                    }
3134                            }
3135                            else
3136                            {
3137                                    mb->directmv[3] = mb->directmv[2] = mb->directmv[1] =
3138                                    mb->directmv[0] = b_mb->mvs[0];
3139    
3140                                    mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3141                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3142                                                                            ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3143                                        : mb->mvs[0].x - mb->directmv[0].x);
3144    
3145                        mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3146                    mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
3147                                                                            ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3148                                        : mb->mvs[0].y - mb->directmv[0].y);
3149    
3150                                    d_sad16 += sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3151                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3152                                                                    i, j, 16, &mb->mvs[0], edged_width),
3153                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3154                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
3155                                                      edged_width);
3156    
3157                }
3158                        d_sad16 += calc_delta_16(mb->deltamv.x, mb->deltamv.y, 1, frame->quant);
3159    
3160                            // forward search
3161                            f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3162                                                    &frame->image, i, j,
3163                                                    mb->mvs[0].x, mb->mvs[0].y,                     /* start point f_directMV */
3164                                                    f_predMV.x, f_predMV.y,                         /* center is f-prediction */
3165                                                    frame->motion_flags,
3166                                                    frame->quant, frame->fcode, pParam,
3167                                                    f_mbs, f_mbs,
3168                                                    &mb->mvs[0], &pmv_dontcare);
3169    
3170    
3171                            // backward search
3172                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3173                                                    &frame->image, i, j,
3174                                                    mb->b_mvs[0].x, mb->b_mvs[0].y,         /* start point b_directMV */
3175                                                    b_predMV.x, b_predMV.y,                         /* center is b-prediction */
3176                                                    frame->motion_flags,
3177                                                    frame->quant, frame->bcode, pParam,
3178                                                    b_mbs, b_mbs,
3179                                                    &mb->b_mvs[0], &pmv_dontcare);
3180    
3181                            i_sad16 =
3182                                    sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3183                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3184                                                                    i, j, 16, &mb->mvs[0], edged_width),
3185                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3186                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
3187                                                      edged_width);
3188                        i_sad16 += calc_delta_16(mb->mvs[0].x-f_predMV.x, mb->mvs[0].y-f_predMV.y,
3189                                                                    frame->fcode, frame->quant);
3190                        i_sad16 += calc_delta_16(mb->b_mvs[0].x-b_predMV.x, mb->b_mvs[0].y-b_predMV.y,
3191                                                                    frame->bcode, frame->quant);
3192    
3193                            // TODO: direct search
3194                            // predictor + delta vector in range [-32,32] (fcode=1)
3195    
3196                            i_sad16 = 65535;
3197                            f_sad16 = 65535;
3198                            b_sad16 = 65535;
3199    //                      d_sad16 = 65535;
3200    
3201                            if (f_sad16 < b_sad16) {
3202                                    best_sad = f_sad16;
3203                                    mb->mode = MODE_FORWARD;
3204                            } else {
3205                                    best_sad = b_sad16;
3206                                    mb->mode = MODE_BACKWARD;
3207                            }
3208    
3209                            if (i_sad16 < best_sad) {
3210                                    best_sad = i_sad16;
3211                                    mb->mode = MODE_INTERPOLATE;
3212                            }
3213    
3214                            if (d_sad16 < best_sad) {
3215    
3216                                    if (b_mb->mode == MODE_INTER4V)
3217                                    {
3218    
3219                                    /* same method of scaling as in decoder.c, so we copy from there */
3220                                for (k = 0; k < 4; k++) {
3221    
3222                                                    mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3223                                mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3224                                                                                            ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3225                                                        : mb->mvs[k].x - mb->directmv[k].x);
3226    
3227                                mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3228                            mb->b_mvs[k].y = (int32_t) ((mb->directmv[k].y == 0)
3229                                                                                            ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3230                                                : mb->mvs[k].y - mb->directmv[k].y);
3231                                            }
3232                                    }
3233                                    else
3234                                    {
3235                                            mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3236    
3237                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3238                                                                                    ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3239                                            : mb->mvs[0].x - mb->directmv[0].x);
3240    
3241                                mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3242    
3243                            mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
3244                                                                                    ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3245                                                : mb->mvs[0].y - mb->directmv[0].y);
3246    
3247                                            mb->mvs[3] = mb->mvs[2] = mb->mvs[1] = mb->mvs[0];
3248                                            mb->b_mvs[3] = mb->b_mvs[2] = mb->b_mvs[1] = mb->b_mvs[0];
3249                    }
3250    
3251                                    best_sad = d_sad16;
3252                                    mb->mode = MODE_DIRECT;
3253                                    mb->mode = MODE_INTERPOLATE;            // direct mode still broken :-(
3254                            }
3255    
3256                            switch (mb->mode)
3257                            {
3258                                    case MODE_FORWARD:
3259                                            f_count++;
3260                                            f_predMV = mb->mvs[0];
3261                                            break;
3262                                    case MODE_BACKWARD:
3263                                            b_count++;
3264                                            b_predMV = mb->b_mvs[0];
3265    
3266                                            break;
3267                                    case MODE_INTERPOLATE:
3268                                            i_count++;
3269                                            f_predMV = mb->mvs[0];
3270                                            b_predMV = mb->b_mvs[0];
3271                                            break;
3272                                    case MODE_DIRECT:
3273                                            d_count++;
3274                                            break;
3275                                    default:
3276                                            s_count++;              // ???
3277                                            break;
3278                            }
3279    
3280                    }
3281            }
3282    
3283    #ifdef _DEBUG_BFRAME_STAT
3284            fprintf(stderr,"B-Stat: F: %04d   B: %04d   I: %04d  D: %04d   S: %04d\n",
3285                                    f_count,b_count,i_count,d_count,s_count);
3286    #endif
3287    
3288    }

Legend:
Removed from v.78  
changed lines
  Added in v.345

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