[svn] / branches / dev-api-4 / xvidcore / src / motion / motion_est.c Repository:
ViewVC logotype

Diff of /branches/dev-api-4/xvidcore/src/motion/motion_est.c

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

revision 3, Fri Mar 8 02:46:11 2002 UTC revision 344, Sat Jul 27 23:07:33 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 133  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 141  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 159  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                            if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
199                                    int32_t deviation;
200    
201                  deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                                  deviation =
202                                            dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
203                                                      pParam->edged_width);
204    
205                  if (deviation < (sad16 - INTER_BIAS))                                  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 312  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 400  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 410  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 418  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 439  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 449  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 464  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          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);  
416            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 485  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 515  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 527  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_DIR(backupMV.x - iDiamondSize,
567                                                                                     backupMV.y - iDiamondSize, 5);
568                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
569                                                                                     backupMV.y - iDiamondSize, 7);
570                                    break;
571                            case 2:
572                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
573                                                                                     2);
574                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
575                                                                                     backupMV.y + iDiamondSize, 6);
576                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
577                                                                                     backupMV.y + iDiamondSize, 8);
578                                    break;
579    
580                            case 3:
581                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
582                                                                                     4);
583                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
584                                                                                     backupMV.y - iDiamondSize, 7);
585                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
586                                                                                     backupMV.y + iDiamondSize, 8);
587                                    break;
588    
589                            case 4:
590                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
591                                                                                     3);
592                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
593                                                                                     backupMV.y - iDiamondSize, 5);
594                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
595                                                                                     backupMV.y + iDiamondSize, 6);
596                                    break;
597    
598                            case 5:
599                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,
600                                                                                     1);
601                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
602                                                                                     3);
603                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
604                                                                                     backupMV.y - iDiamondSize, 5);
605                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
606                                                                                     backupMV.y + iDiamondSize, 6);
607                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
608                                                                                     backupMV.y - iDiamondSize, 7);
609                                    break;
610    
611                            case 6:
612                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
613                                                                                     2);
614                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
615                                                                                     3);
616    
617                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
618                                                                                     backupMV.y - iDiamondSize, 5);
619                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
620                                                                                     backupMV.y + iDiamondSize, 6);
621                                    CHECK_MV16_CANDIDATE_DIR(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_DIR(backupMV.x, backupMV.y + iDiamondSize,
630                                                                                     4);
631                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
632                                                                                     backupMV.y - iDiamondSize, 5);
633                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
634                                                                                     backupMV.y - iDiamondSize, 7);
635                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
636                                                                                     backupMV.y + iDiamondSize, 8);
637                                    break;
638    
639                            case 8:
640                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
641                                                                                     2);
642                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
643                                                                                     4);
644                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
645                                                                                     backupMV.y + iDiamondSize, 6);
646                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
647                                                                                     backupMV.y - iDiamondSize, 7);
648                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
649                                                                                     backupMV.y + iDiamondSize, 8);
650                                    break;
651                            default:
652                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,
653                                                                                     1);
654                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
655                                                                                     2);
656                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
657                                                                                     3);
658                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
659                                                                                     4);
660    
661                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
662                                                                                     backupMV.y - iDiamondSize, 5);
663                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
664                                                                                     backupMV.y + iDiamondSize, 6);
665                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
666                                                                                     backupMV.y - iDiamondSize, 7);
667                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
668                                                                                     backupMV.y + iDiamondSize, 8);
669                                    break;
670                            }
671            } else {
672                    currMV->x = start_x;
673                    currMV->y = start_y;
674            }
675          return iMinSAD;          return iMinSAD;
676  }  }
677    
 #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  
678    
679  int32_t PMVfastSearch16(  int32_t
680                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
681                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
682                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
683                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
684                                          const IMAGE * const pCur,                                    const uint8_t * const cur,
685                                          const int x, const int y,                                    const int x,
686                                          const uint32_t MotionFlags,                                    const int y,
687                                          MBParam * const pParam,                                     const int start_x,
688                                          MACROBLOCK * const pMBs,                                     const int start_y,
689                                       int iMinSAD,
690                                          VECTOR * const currMV,                                          VECTOR * const currMV,
691                                          VECTOR * const currPMV)                                     const int center_x,
692                                       const int center_y,
693                                      const int32_t min_dx,
694                                      const int32_t max_dx,
695                                      const int32_t min_dy,
696                                      const int32_t max_dy,
697                                      const int32_t iEdgedWidth,
698                                      const int32_t iDiamondSize,
699                                      const int32_t iFcode,
700                                      const int32_t iQuant,
701                                      int iFound)
702  {  {
703          const uint32_t iWcount = pParam->mb_width;          int32_t iSAD;
704          const int32_t iFcode = pParam->fixed_code;          int32_t dx, dy;
705          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;  
706    
707          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          backupMV.x = start_x;
708            backupMV.y = start_y;
709    
710          int32_t iDiamondSize;          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
711                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
712                            NOCHECK_MV16_CANDIDATE(dx, dy);
713    
714          int32_t min_dx;          return iMinSAD;
715          int32_t max_dx;  }
         int32_t min_dy;  
         int32_t max_dy;  
716    
717          int32_t iFound;  int32_t
718    AdvDiamond16_MainSearch(const uint8_t * const pRef,
719                                                    const uint8_t * const pRefH,
720                                                    const uint8_t * const pRefV,
721                                                    const uint8_t * const pRefHV,
722                                                    const uint8_t * const cur,
723                                                    const int x,
724                                                    const int y,
725                                               int start_x,
726                                               int start_y,
727                                               int iMinSAD,
728                                               VECTOR * const currMV,
729                                               const int center_x,
730                                               const int center_y,
731                                                    const int32_t min_dx,
732                                                    const int32_t max_dx,
733                                                    const int32_t min_dy,
734                                                    const int32_t max_dy,
735                                                    const int32_t iEdgedWidth,
736                                                    const int32_t iDiamondSize,
737                                                    const int32_t iFcode,
738                                                    const int32_t iQuant,
739                                                    int iDirection)
740    {
741    
742          VECTOR newMV;          int32_t iSAD;
         VECTOR backupMV;        /* just for PMVFAST */  
743    
744          VECTOR pmv[4];  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
         int32_t psad[4];  
745    
746          MACROBLOCK * const pMB = pMBs + x + y * iWcount;          if (iDirection) {
747                    CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
748                    CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
749                    CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
750                    CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
751            } else {
752                    int bDirection = 1 + 2 + 4 + 8;
753    
754                    do {
755                            iDirection = 0;
756                            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)
757                                    CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
758    
759                            if (bDirection & 2)
760                                    CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
761    
762                            if (bDirection & 4)
763                                    CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
764    
765                            if (bDirection & 8)
766                                    CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
767    
768                            /* now we're doing diagonal checks near our candidate */
769    
770                            if (iDirection)         //checking if anything found
771                            {
772                                    bDirection = iDirection;
773                                    iDirection = 0;
774                                    start_x = currMV->x;
775                                    start_y = currMV->y;
776                                    if (bDirection & 3)     //our candidate is left or right
777                                    {
778                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
779                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
780                                    } else                  // what remains here is up or down
781                                    {
782                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
783                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
784                                    }
785    
786                                    if (iDirection) {
787                                            bDirection += iDirection;
788                                            start_x = currMV->x;
789                                            start_y = currMV->y;
790                                    }
791                            } else                          //about to quit, eh? not so fast....
792                            {
793                                    switch (bDirection) {
794                                    case 2:
795                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
796                                                                                             start_y - iDiamondSize, 2 + 4);
797                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
798                                                                                             start_y + iDiamondSize, 2 + 8);
799                                            break;
800                                    case 1:
801    
802                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
803                                                                                             start_y - iDiamondSize, 1 + 4);
804                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
805                                                                                             start_y + iDiamondSize, 1 + 8);
806                                            break;
807                                    case 2 + 4:
808                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
809                                                                                             start_y - iDiamondSize, 1 + 4);
810                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
811                                                                                             start_y - iDiamondSize, 2 + 4);
812                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
813                                                                                             start_y + iDiamondSize, 2 + 8);
814                                            break;
815                                    case 4:
816                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
817                                                                                             start_y - iDiamondSize, 2 + 4);
818                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
819                                                                                             start_y - iDiamondSize, 1 + 4);
820                                            break;
821                                    case 8:
822                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
823                                                                                             start_y + iDiamondSize, 2 + 8);
824                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
825                                                                                             start_y + iDiamondSize, 1 + 8);
826                                            break;
827                                    case 1 + 4:
828                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
829                                                                                             start_y + iDiamondSize, 1 + 8);
830                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
831                                                                                             start_y - iDiamondSize, 1 + 4);
832                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
833                                                                                             start_y - iDiamondSize, 2 + 4);
834                                            break;
835                                    case 2 + 8:
836                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
837                                                                                             start_y - iDiamondSize, 1 + 4);
838                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
839                                                                                             start_y + iDiamondSize, 1 + 8);
840                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
841                                                                                             start_y + iDiamondSize, 2 + 8);
842                                            break;
843                                    case 1 + 8:
844                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
845                                                                                             start_y - iDiamondSize, 2 + 4);
846                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
847                                                                                             start_y + iDiamondSize, 2 + 8);
848                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
849                                                                                             start_y + iDiamondSize, 1 + 8);
850                                            break;
851                                    default:                //1+2+4+8 == we didn't find anything at all
852                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
853                                                                                             start_y - iDiamondSize, 1 + 4);
854                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
855                                                                                             start_y + iDiamondSize, 1 + 8);
856                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
857                                                                                             start_y - iDiamondSize, 2 + 4);
858                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
859                                                                                             start_y + iDiamondSize, 2 + 8);
860                                            break;
861                                    }
862                                    if (!iDirection)
863                                            break;          //ok, the end. really
864                                    else {
865                                            bDirection = iDirection;
866                                            start_x = currMV->x;
867                                            start_y = currMV->y;
868                                    }
869                            }
870                    }
871                    while (1);                              //forever
872            }
873            return iMinSAD;
874    }
875    
         static int32_t threshA,threshB;  
         int32_t bPredEq;  
         int32_t iMinSAD,iSAD;  
876    
877  /* Get maximum range */  #define CHECK_MV16_F_INTERPOL(X,Y,BX,BY) { \
878          get_range(&min_dx, &max_dx, &min_dy, &max_dy,    if ( ((X) <= max_dx) && ((X) >= min_dx) \
879                          x, y, 16, iWidth, iHeight, iFcode);      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
880      { \
881        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
882        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
883        if (iSAD < iMinSAD) \
884        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
885    }
886    
887  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  #define CHECK_MV16_F_INTERPOL_DIR(X,Y,BX,BY,D) { \
888      if ( ((X) <= max_dx) && ((X) >= min_dx) \
889        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
890      { \
891        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
892        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
893        if (iSAD < iMinSAD) \
894        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
895    }
896    
897          if (!(MotionFlags & PMV_HALFPEL16 ))  #define CHECK_MV16_F_INTERPOL_FOUND(X,Y,BX,BY,D) { \
898          { min_dx = EVEN(min_dx);    if ( ((X) <= max_dx) && ((X) >= min_dx) \
899            max_dx = EVEN(max_dx);      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
900            min_dy = EVEN(min_dy);    { \
901            max_dy = EVEN(max_dy);      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
902          }               /* 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);\
903        if (iSAD < iMinSAD) \
904        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
905    }
906    
907    
908          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);  #define CHECK_MV16_B_INTERPOL(FX,FY,X,Y) { \
909      if ( ((X) <= max_dx) && ((X) >= min_dx) \
910        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
911      { \
912        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
913        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
914        if (iSAD < iMinSAD) \
915        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
916    }
917    
918          if ((x==0) && (y==0) )  
919    #define CHECK_MV16_B_INTERPOL_DIR(FX,FY,X,Y,D) { \
920      if ( ((X) <= max_dx) && ((X) >= min_dx) \
921        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
922      { \
923        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
924        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
925        if (iSAD < iMinSAD) \
926        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
927    }
928    
929    
930    #define CHECK_MV16_B_INTERPOL_FOUND(FX,FY,X,Y,D) { \
931      if ( ((X) <= max_dx) && ((X) >= min_dx) \
932        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
933      { \
934        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
935        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
936        if (iSAD < iMinSAD) \
937        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
938    }
939    
940    
941    #if (0==1)
942    int32_t
943    Diamond16_InterpolMainSearch(
944                                            const uint8_t * const f_pRef,
945                                             const uint8_t * const f_pRefH,
946                                             const uint8_t * const f_pRefV,
947                                             const uint8_t * const f_pRefHV,
948                                             const uint8_t * const cur,
949    
950                                            const uint8_t * const b_pRef,
951                                             const uint8_t * const b_pRefH,
952                                             const uint8_t * const b_pRefV,
953                                             const uint8_t * const b_pRefHV,
954    
955                                             const int x,
956                                             const int y,
957    
958                                       const int f_start_x,
959                                       const int f_start_y,
960                                       const int b_start_x,
961                                       const int b_start_y,
962    
963                                       int iMinSAD,
964                                       VECTOR * const f_currMV,
965                                       VECTOR * const b_currMV,
966    
967                                       const int f_center_x,
968                                       const int f_center_y,
969                                       const int b_center_x,
970                                       const int b_center_y,
971    
972                                             const int32_t min_dx,
973                                             const int32_t max_dx,
974                                             const int32_t min_dy,
975                                             const int32_t max_dy,
976                                             const int32_t iEdgedWidth,
977                                             const int32_t iDiamondSize,
978    
979                                             const int32_t f_iFcode,
980                                             const int32_t b_iFcode,
981    
982                                             const int32_t iQuant,
983                                             int iFound)
984          {          {
985                  threshA =  512;  /* Do a diamond search around given starting point, return SAD of best */
986                  threshB = 1024;  
987            int32_t f_iDirection = 0;
988            int32_t b_iDirection = 0;
989            int32_t iSAD;
990    
991            VECTOR f_backupMV;
992            VECTOR b_backupMV;
993    
994            f_backupMV.x = start_x;
995            f_backupMV.y = start_y;
996            b_backupMV.x = start_x;
997            b_backupMV.y = start_y;
998    
999    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1000    
1001            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1002            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1003            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1004            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1005    
1006            if (iDirection)
1007                    while (!iFound) {
1008                            iFound = 1;
1009                            backupMV = *currMV;
1010    
1011                            if (iDirection != 2)
1012                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1013                                                                                       backupMV.y, 1);
1014                            if (iDirection != 1)
1015                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1016                                                                                       backupMV.y, 2);
1017                            if (iDirection != 4)
1018                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1019                                                                                       backupMV.y - iDiamondSize, 3);
1020                            if (iDirection != 3)
1021                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1022                                                                                       backupMV.y + iDiamondSize, 4);
1023            } else {
1024                    currMV->x = start_x;
1025                    currMV->y = start_y;
1026          }          }
1027          else          return iMinSAD;
1028    }
1029    #endif
1030    
1031    
1032    int32_t
1033    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1034                                               const uint8_t * const pRefH,
1035                                               const uint8_t * const pRefV,
1036                                               const uint8_t * const pRefHV,
1037                                               const uint8_t * const cur,
1038                                               const int x,
1039                                               const int y,
1040                                               int start_x,
1041                                               int start_y,
1042                                               int iMinSAD,
1043                                               VECTOR * const currMV,
1044                                               const int center_x,
1045                                               const int center_y,
1046                                               const int32_t min_dx,
1047                                               const int32_t max_dx,
1048                                               const int32_t min_dy,
1049                                               const int32_t max_dy,
1050                                               const int32_t iEdgedWidth,
1051                                               const int32_t iDiamondSize,
1052                                               const int32_t iFcode,
1053                                               const int32_t iQuant,
1054                                               int iDirection)
1055          {          {
1056                  threshA = psad[0];  
1057                  threshB = threshA+256;          int32_t iSAD;
1058                  if (threshA< 512) threshA =  512;  
1059                  if (threshA>1024) threshA = 1024;  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1060                  if (threshB>1792) threshB = 1792;  
1061            if (iDirection) {
1062                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1063                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1064                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1065                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1066            } else {
1067                    int bDirection = 1 + 2 + 4 + 8;
1068    
1069                    do {
1070                            iDirection = 0;
1071                            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)
1072                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1073    
1074                            if (bDirection & 2)
1075                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1076    
1077                            if (bDirection & 4)
1078                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1079    
1080                            if (bDirection & 8)
1081                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1082    
1083                            /* now we're doing diagonal checks near our candidate */
1084    
1085                            if (iDirection)         //checking if anything found
1086                            {
1087                                    bDirection = iDirection;
1088                                    iDirection = 0;
1089                                    start_x = currMV->x;
1090                                    start_y = currMV->y;
1091                                    if (bDirection & 3)     //our candidate is left or right
1092                                    {
1093                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1094                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1095                                    } else                  // what remains here is up or down
1096                                    {
1097                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1098                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1099                                    }
1100    
1101                                    if (iDirection) {
1102                                            bDirection += iDirection;
1103                                            start_x = currMV->x;
1104                                            start_y = currMV->y;
1105                                    }
1106                            } else                          //about to quit, eh? not so fast....
1107                            {
1108                                    switch (bDirection) {
1109                                    case 2:
1110                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1111                                                                                            start_y - iDiamondSize, 2 + 4);
1112                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1113                                                                                            start_y + iDiamondSize, 2 + 8);
1114                                            break;
1115                                    case 1:
1116                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1117                                                                                            start_y - iDiamondSize, 1 + 4);
1118                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1119                                                                                            start_y + iDiamondSize, 1 + 8);
1120                                            break;
1121                                    case 2 + 4:
1122                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1123                                                                                            start_y - iDiamondSize, 1 + 4);
1124                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1125                                                                                            start_y - iDiamondSize, 2 + 4);
1126                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1127                                                                                            start_y + iDiamondSize, 2 + 8);
1128                                            break;
1129                                    case 4:
1130                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1131                                                                                            start_y - iDiamondSize, 2 + 4);
1132                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1133                                                                                            start_y - iDiamondSize, 1 + 4);
1134                                            break;
1135                                    case 8:
1136                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1137                                                                                            start_y + iDiamondSize, 2 + 8);
1138                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1139                                                                                            start_y + iDiamondSize, 1 + 8);
1140                                            break;
1141                                    case 1 + 4:
1142                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1143                                                                                            start_y + iDiamondSize, 1 + 8);
1144                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1145                                                                                            start_y - iDiamondSize, 1 + 4);
1146                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1147                                                                                            start_y - iDiamondSize, 2 + 4);
1148                                            break;
1149                                    case 2 + 8:
1150                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1151                                                                                            start_y - iDiamondSize, 1 + 4);
1152                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1153                                                                                            start_y + iDiamondSize, 1 + 8);
1154                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1155                                                                                            start_y + iDiamondSize, 2 + 8);
1156                                            break;
1157                                    case 1 + 8:
1158                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1159                                                                                            start_y - iDiamondSize, 2 + 4);
1160                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1161                                                                                            start_y + iDiamondSize, 2 + 8);
1162                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1163                                                                                            start_y + iDiamondSize, 1 + 8);
1164                                            break;
1165                                    default:                //1+2+4+8 == we didn't find anything at all
1166                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1167                                                                                            start_y - iDiamondSize, 1 + 4);
1168                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1169                                                                                            start_y + iDiamondSize, 1 + 8);
1170                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1171                                                                                            start_y - iDiamondSize, 2 + 4);
1172                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1173                                                                                            start_y + iDiamondSize, 2 + 8);
1174                                            break;
1175                                    }
1176                                    if (!(iDirection))
1177                                            break;          //ok, the end. really
1178                                    else {
1179                                            bDirection = iDirection;
1180                                            start_x = currMV->x;
1181                                            start_y = currMV->y;
1182                                    }
1183                            }
1184                    }
1185                    while (1);                              //forever
1186            }
1187            return iMinSAD;
1188          }          }
1189    
         iFound=0;  
1190    
1191  /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  int32_t
1192          vector of the median.  Full8_MainSearch(const uint8_t * const pRef,
1193          If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2                                   const uint8_t * const pRefH,
1194  */                                   const uint8_t * const pRefV,
1195                                     const uint8_t * const pRefHV,
1196                                     const uint8_t * const cur,
1197                                     const int x,
1198                                     const int y,
1199                               const int start_x,
1200                               const int start_y,
1201                               int iMinSAD,
1202                               VECTOR * const currMV,
1203                               const int center_x,
1204                               const int center_y,
1205                                     const int32_t min_dx,
1206                                     const int32_t max_dx,
1207                                     const int32_t min_dy,
1208                                     const int32_t max_dy,
1209                                     const int32_t iEdgedWidth,
1210                                     const int32_t iDiamondSize,
1211                                     const int32_t iFcode,
1212                                     const int32_t iQuant,
1213                                     int iFound)
1214    {
1215            int32_t iSAD;
1216            int32_t dx, dy;
1217            VECTOR backupMV;
1218    
1219          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )          backupMV.x = start_x;
1220                  iFound=2;          backupMV.y = start_y;
1221    
1222  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1223          Otherwise select large Diamond Search.                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
1224  */                          NOCHECK_MV8_CANDIDATE(dx, dy);
1225    
1226          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )          return iMinSAD;
1227                  iDiamondSize=1; // halfpel!  }
         else  
                 iDiamondSize=2; // halfpel!  
1228    
1229          if (!(MotionFlags & PMV_HALFPELDIAMOND16) )  Halfpel8_RefineFuncPtr Halfpel8_Refine;
1230                  iDiamondSize*=2;  
1231    int32_t
1232    Halfpel16_Refine(const uint8_t * const pRef,
1233                                     const uint8_t * const pRefH,
1234                                     const uint8_t * const pRefV,
1235                                     const uint8_t * const pRefHV,
1236                                     const uint8_t * const cur,
1237                                     const int x,
1238                                     const int y,
1239                                     VECTOR * const currMV,
1240                                     int32_t iMinSAD,
1241                               const int center_x,
1242                               const int center_y,
1243                                     const int32_t min_dx,
1244                                     const int32_t max_dx,
1245                                     const int32_t min_dy,
1246                                     const int32_t max_dy,
1247                                     const int32_t iFcode,
1248                                     const int32_t iQuant,
1249                                     const int32_t iEdgedWidth)
1250    {
1251    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1252    
1253            int32_t iSAD;
1254            VECTOR backupMV = *currMV;
1255    
1256            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1257            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y - 1);
1258            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1259            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y);
1260            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y);
1261            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1262            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y + 1);
1263            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1264    
1265            return iMinSAD;
1266    }
1267    
1268    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1269    
1270    
1271    
1272    int32_t
1273    PMVfastSearch16(const uint8_t * const pRef,
1274                                    const uint8_t * const pRefH,
1275                                    const uint8_t * const pRefV,
1276                                    const uint8_t * const pRefHV,
1277                                    const IMAGE * const pCur,
1278                                    const int x,
1279                                    const int y,
1280                                    const int start_x,
1281                                    const int start_y,
1282                                    const int center_x,
1283                                    const int center_y,
1284                                    const uint32_t MotionFlags,
1285                                    const uint32_t iQuant,
1286                                    const uint32_t iFcode,
1287                                    const MBParam * const pParam,
1288                                    const MACROBLOCK * const pMBs,
1289                                    const MACROBLOCK * const prevMBs,
1290                                    VECTOR * const currMV,
1291                                    VECTOR * const currPMV)
1292    {
1293            const uint32_t iWcount = pParam->mb_width;
1294            const int32_t iWidth = pParam->width;
1295            const int32_t iHeight = pParam->height;
1296            const int32_t iEdgedWidth = pParam->edged_width;
1297    
1298            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
1299    
1300            int32_t iDiamondSize;
1301    
1302            int32_t min_dx;
1303            int32_t max_dx;
1304            int32_t min_dy;
1305            int32_t max_dy;
1306    
1307            int32_t iFound;
1308    
1309            VECTOR newMV;
1310            VECTOR backupMV;                        /* just for PMVFAST */
1311    
1312            VECTOR pmv[4];
1313            int32_t psad[4];
1314    
1315            MainSearch16FuncPtr MainSearchPtr;
1316    
1317            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1318    
1319            int32_t threshA, threshB;
1320            int32_t bPredEq;
1321            int32_t iMinSAD, iSAD;
1322    
1323    /* Get maximum range */
1324            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1325                              iFcode);
1326    
1327    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1328    
1329            if (!(MotionFlags & PMV_HALFPEL16)) {
1330                    min_dx = EVEN(min_dx);
1331                    max_dx = EVEN(max_dx);
1332                    min_dy = EVEN(min_dy);
1333                    max_dy = EVEN(max_dy);
1334            }
1335    
1336            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1337            //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1338            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1339    
1340            if ((x == 0) && (y == 0)) {
1341                    threshA = 512;
1342                    threshB = 1024;
1343            } else {
1344                    threshA = psad[0];
1345                    threshB = threshA + 256;
1346                    if (threshA < 512)
1347                            threshA = 512;
1348                    if (threshA > 1024)
1349                            threshA = 1024;
1350                    if (threshB > 1792)
1351                            threshB = 1792;
1352            }
1353    
1354            iFound = 0;
1355    
1356  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1357          MinSAD=SAD          MinSAD=SAD
# Line 688  Line 1360 
1360          If SAD<=256 goto Step 10.          If SAD<=256 goto Step 10.
1361  */  */
1362    
1363            currMV->x = start_x;
1364            currMV->y = start_y;
1365    
1366  // 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! */  
1367                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1368                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1369          }          }
1370    
1371          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
                 {  
1372                          currMV->x=max_dx;                          currMV->x=max_dx;
1373                  }                  }
1374          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
                 {  
1375                          currMV->x=min_dx;                          currMV->x=min_dx;
1376                  }                  }
1377          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
                 {  
1378                          currMV->y=max_dy;                          currMV->y=max_dy;
1379                  }                  }
1380          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
                 {  
1381                          currMV->y=min_dy;                          currMV->y=min_dy;
1382                  }                  }
1383    
1384          iMinSAD = sad16( cur,          iMinSAD =
1385                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1386                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1387          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1388            iMinSAD +=
1389          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1390                  {                                            (uint8_t) iFcode, iQuant);
1391    
1392            if ((iMinSAD < 256) ||
1393                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1394                     ((int32_t) iMinSAD < prevMB->sad16))) {
1395                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1396                    {
1397                            if (!MVzero(*currMV)) {
1398                                    iMinSAD += MV16_00_BIAS;
1399                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1400                                    iMinSAD -= MV16_00_BIAS;
1401                            }
1402                    }
1403    
1404                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1405                                  goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1406                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
1407                                  goto step10;                          goto PMVfast16_Terminate_with_Refine;
1408                  }                  }
1409    
1410    
1411    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1412       vector of the median.
1413       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1414    */
1415    
1416            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1417                    iFound = 2;
1418    
1419    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1420       Otherwise select large Diamond Search.
1421    */
1422    
1423            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1424                    iDiamondSize = 1;               // halfpel!
1425            else
1426                    iDiamondSize = 2;               // halfpel!
1427    
1428            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1429                    iDiamondSize *= 2;
1430    
1431  /*  /*
1432  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.
1433          Also calculate (0,0) but do not subtract offset.          Also calculate (0,0) but do not subtract offset.
1434          Let MinSAD be the smallest SAD up to this point.          Let MinSAD be the smallest SAD up to this point.
1435          If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1436  */  */
1437    
1438  // (0,0) is always possible  // (0,0) is always possible
1439    
1440            if (!MVzero(pmv[0]))
1441          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1442    
1443  // previous frame MV is always possible  // previous frame MV is always possible
1444          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
1445            if (!MVzero(prevMB->mvs[0]))
1446                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1447                            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
1448    
1449  // left neighbour, if allowed  // left neighbour, if allowed
1450          if (x != 0)  
1451          {          if (!MVzero(pmv[1]))
1452                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1453                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1454                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1455                                            pmv[1].x = EVEN(pmv[1].x);
1456                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
1457                  }                  }
1458    
1459                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1460          }          }
   
1461  // top neighbour, if allowed  // top neighbour, if allowed
1462          if (y != 0)          if (!MVzero(pmv[2]))
1463          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1464                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1465                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1466                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1467                                                    pmv[2].x = EVEN(pmv[2].x);
1468                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
1469                  }                  }
1470                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1471    
1472  // top right neighbour, if allowed  // top right neighbour, if allowed
1473                  if (x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1474                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1475                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1476                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1477                                                                            if (!MVequal(pmv[3], pmv[2])) {
1478                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1479                                                                                            pmv[3].x = EVEN(pmv[3].x);
1480                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
1481                          }                          }
1482                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1483                                                                                                                             pmv[3].y);
1484                  }                  }
1485          }          }
1486    
1487            if ((MVzero(*currMV)) &&
1488                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1489                    iMinSAD -= MV16_00_BIAS;
1490    
1491    
1492  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1493     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.
1494  */  */
1495    
1496          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1497                  {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1498                     ((int32_t) iMinSAD < prevMB->sad16))) {
1499                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1500                                  goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1501                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
1502                                  goto step10;                          goto PMVfast16_Terminate_with_Refine;
1503                  }                  }
1504    
1505    
# Line 796  Line 1513 
1513          Refine by using small diamond and goto step 10.          Refine by using small diamond and goto step 10.
1514  */  */
1515    
1516            if (MotionFlags & PMV_USESQUARES16)
1517                    MainSearchPtr = Square16_MainSearch;
1518            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1519                    MainSearchPtr = AdvDiamond16_MainSearch;
1520            else
1521                    MainSearchPtr = Diamond16_MainSearch;
1522    
1523          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1524    
1525    
1526  /* 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 */
1527          iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1528                  x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1529                  currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1530                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1531                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1532                                                      iQuant, iFound);
1533    
1534          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1535                  *currMV = newMV;                  *currMV = newMV;
1536                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1537          }          }
1538    
1539          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1540  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1541    
1542                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1543                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1544                                  x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1545                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1546                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1547                                                                      iDiamondSize, iFcode, iQuant, iFound);
1548    
1549                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
1550                                  *currMV = newMV;                                  *currMV = newMV;
1551                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
1552                          }                          }
1553                  }                  }
1554    
1555                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1556                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1557                                  x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1558                          0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1559                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1560                                                                      iEdgedWidth, iDiamondSize, iFcode,
1561                                                                      iQuant, iFound);
1562    
1563                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
1564                                  *currMV = newMV;                                  *currMV = newMV;
1565                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
1566                          }                          }
# Line 845  Line 1571 
1571          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.
1572  */  */
1573    
1574  step10:    PMVfast16_Terminate_with_Refine:
1575          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1576                  iMinSAD = PMVfastSearch16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1577                                  x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1578                                  currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1579                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1580    
1581  step10b:    PMVfast16_Terminate_without_Refine:
1582          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1583          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1584          return iMinSAD;          return iMinSAD;
1585  }  }
1586    
# Line 863  Line 1589 
1589    
1590    
1591    
1592  int32_t PMVfastSearch8_MainSearch(  int32_t
1593                                          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1594                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1595                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1596                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1597                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1598                                          const int x, const int y,                                          const int x,
1599                                          int32_t startx, int32_t starty,                                          const int y,
1600                                            int32_t start_x,
1601                                            int32_t start_y,
1602                                          int32_t iMinSAD,                                          int32_t iMinSAD,
1603                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1604                                          const VECTOR * const pmv,                                     const int center_x,
1605                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
1606                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1607                                            const int32_t max_dx,
1608                                            const int32_t min_dy,
1609                                            const int32_t max_dy,
1610                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
1611                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
1612                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 885  Line 1616 
1616  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1617    
1618          int32_t iDirection=0;          int32_t iDirection=0;
1619            int32_t iDirectionBackup;
1620          int32_t iSAD;          int32_t iSAD;
1621          VECTOR backupMV;          VECTOR backupMV;
1622          backupMV.x = startx;  
1623          backupMV.y = starty;          backupMV.x = start_x;
1624            backupMV.y = start_y;
1625    
1626  /* 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 */
1627    
# Line 897  Line 1630 
1630          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1631          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1632    
1633          if (iDirection)          if (iDirection) {
1634                  while (!iFound)                  while (!iFound) {
                 {  
1635                          iFound = 1;                          iFound = 1;
1636                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1637                            iDirectionBackup = iDirection;
1638    
1639                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1640                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1641                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1642                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1643                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1644                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1645                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1646                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1647                                                                                      backupMV.y - iDiamondSize, 3);
1648                            if (iDirectionBackup != 3)
1649                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1650                                                                                      backupMV.y + iDiamondSize, 4);
1651                  }                  }
1652          else          } else {
1653                  {                  currMV->x = start_x;
1654                          currMV->x = startx;                  currMV->y = start_y;
                         currMV->y = starty;  
1655                  }                  }
1656          return iMinSAD;          return iMinSAD;
1657  }  }
1658    
1659  int32_t PMVfastSearch8_Refine(  int32_t
1660                                          const uint8_t * const pRef,  Halfpel8_Refine_c(const uint8_t * const pRef,
1661                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1662                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1663                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1664                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1665                                          const int x, const int y,                                  const int x,
1666                                    const int y,
1667                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1668                                          int32_t iMinSAD,                                          int32_t iMinSAD,
1669                                          const VECTOR * const pmv,                             const int center_x,
1670                                          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1671                                          const int32_t min_dy, const int32_t max_dy,                                  const int32_t min_dx,
1672                                    const int32_t max_dx,
1673                                    const int32_t min_dy,
1674                                    const int32_t max_dy,
1675                                          const int32_t iFcode,                                          const int32_t iFcode,
1676                                          const int32_t iQuant,                                          const int32_t iQuant,
1677                                          const int32_t iEdgedWidth)                                          const int32_t iEdgedWidth)
# Line 956  Line 1696 
1696    
1697  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1698    
1699  int32_t PMVfastSearch8(  int32_t
1700                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1701                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1702                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1703                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1704                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1705                                          const int x, const int y,                             const int x,
1706                                          const int start_x, int start_y,                             const int y,
1707                               const int start_x,
1708                               const int start_y,
1709                                    const int center_x,
1710                                    const int center_y,
1711                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1712                                          MBParam * const pParam,                             const uint32_t iQuant,
1713                                          MACROBLOCK * const pMBs,                             const uint32_t iFcode,
1714                               const MBParam * const pParam,
1715                               const MACROBLOCK * const pMBs,
1716                               const MACROBLOCK * const prevMBs,
1717                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1718                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1719  {  {
1720          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;  
1721          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1722          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1723          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 991  Line 1735 
1735          int32_t psad[4];          int32_t psad[4];
1736          VECTOR newMV;          VECTOR newMV;
1737          VECTOR backupMV;          VECTOR backupMV;
1738            VECTOR startMV;
1739    
1740          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1741            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
1742    
1743          static int32_t threshA,threshB;           int32_t threshA, threshB;
1744          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1745          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1746    
1747          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1748    
1749  /* Get maximum range */          MainSearch8FuncPtr MainSearchPtr;
     get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                         x, y, 8, iWidth, iHeight, iFcode);  
1750    
1751  /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */          /* Init variables */
1752            startMV.x = start_x;
1753            startMV.y = start_y;
1754    
1755          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          /* Get maximum range */
1756          { min_dx = EVEN(min_dx);          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
1757                              iFcode);
1758    
1759            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
1760                    min_dx = EVEN(min_dx);
1761            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
1762            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
1763            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
1764          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
1765    
1766          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1767            //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
1768            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
1769    
1770          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1771                  threshA =  512/4;                  threshA =  512/4;
1772                  threshB = 1024/4;                  threshB = 1024/4;
1773    
1774          }          } else {
1775          else                  threshA = psad[0] / 4;  /* good estimate? */
         {  
                 threshA = psad[0]/4;                    /* good estimate */  
1776                  threshB = threshA+256/4;                  threshB = threshA+256/4;
1777                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
1778                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
1779                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
1780                            threshA = 1024 / 4;
1781                    if (threshB > 1792 / 4)
1782                            threshB = 1792 / 4;
1783          }          }
1784    
1785          iFound=0;          iFound=0;
1786    
1787  /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  /* Step 4: Calculate SAD around the Median prediction.
1788       MinSAD=SAD
1789       If Motion Vector equal to Previous frame motion vector
1790       and MinSAD<PrevFrmSAD goto Step 10.
1791       If SAD<=256 goto Step 10.
1792    */
1793    
1794    
1795    // Prepare for main loop
1796    
1797    //  if (MotionFlags & PMV_USESQUARES8)
1798    //      MainSearchPtr = Square8_MainSearch;
1799    //  else
1800    
1801            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1802                    MainSearchPtr = AdvDiamond8_MainSearch;
1803            else
1804                    MainSearchPtr = Diamond8_MainSearch;
1805    
1806    
1807            *currMV = startMV;
1808    
1809            iMinSAD =
1810                    sad8(cur,
1811                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
1812                                                    iEdgedWidth), iEdgedWidth);
1813            iMinSAD +=
1814                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
1815                                             (uint8_t) iFcode, iQuant);
1816    
1817            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
1818                                                                    && ((int32_t) iMinSAD <
1819                                                                            prevMB->sad8[iSubBlock]))) {
1820                    if (MotionFlags & PMV_QUICKSTOP16)
1821                            goto PMVfast8_Terminate_without_Refine;
1822                    if (MotionFlags & PMV_EARLYSTOP16)
1823                            goto PMVfast8_Terminate_with_Refine;
1824            }
1825    
1826    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1827          vector of the median.          vector of the median.
1828          If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2          If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1829  */  */
1830    
1831          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )          if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
1832                  iFound=2;                  iFound=2;
1833    
1834  /* 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.
1835          Otherwise select large Diamond Search.          Otherwise select large Diamond Search.
1836  */  */
1837    
1838          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )          if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
1839                  iDiamondSize=1; // 1 halfpel!                  iDiamondSize=1; // 1 halfpel!
1840          else          else
1841                  iDiamondSize=2; // 2 halfpel = 1 full pixel!                  iDiamondSize=2; // 2 halfpel = 1 full pixel!
# Line 1053  Line 1843 
1843          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
1844                  iDiamondSize*=2;                  iDiamondSize*=2;
1845    
 /* 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;  
                 }  
1846    
1847  /*  /*
1848  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.
1849          Also calculate (0,0) but do not subtract offset.          Also calculate (0,0) but do not subtract offset.
1850          Let MinSAD be the smallest SAD up to this point.          Let MinSAD be the smallest SAD up to this point.
1851          If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1852  */  */
1853    
1854  // 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);  
1855    
1856  // (0,0) is always possible          if (!MVequal(pmv[0], startMV))
1857                    CHECK_MV8_CANDIDATE(center_x, center_y);
1858    
1859    // (0,0) if needed
1860            if (!MVzero(pmv[0]))
1861                    if (!MVzero(startMV))
1862          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1863    
1864  // previous frame MV is always possible  // previous frame MV if needed
1865          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
1866                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
1867                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
1868                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
1869                                                                            prevMB->mvs[iSubBlock].y);
1870    
1871            if ((iMinSAD <= threshA) ||
1872                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1873                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1874                    if (MotionFlags & PMV_QUICKSTOP16)
1875                            goto PMVfast8_Terminate_without_Refine;
1876                    if (MotionFlags & PMV_EARLYSTOP16)
1877                            goto PMVfast8_Terminate_with_Refine;
1878            }
1879    
1880  // left neighbour, if allowed  // left neighbour, if allowed and needed
1881          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
1882          {                  if (!MVequal(pmv[1], startMV))
1883                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
1884                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
1885                                            if (!(MotionFlags & PMV_HALFPEL8)) {
1886                                                    pmv[1].x = EVEN(pmv[1].x);
1887                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
1888                  }                  }
1889                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1890          }          }
1891    // top neighbour, if allowed and needed
1892  // top neighbour, if allowed          if (!MVzero(pmv[2]))
1893          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
1894          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
1895                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
1896                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
1897                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
1898                                                            pmv[2].x = EVEN(pmv[2].x);
1899                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
1900                  }                  }
1901                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1902    
1903  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
1904                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
1905                  {                                                          if (!MVequal(pmv[3], startMV))
1906                  if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
1907                  {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
1908                                                                                    if (!MVequal(pmv[3], pmv[1]))
1909                                                                                            if (!MVequal(pmv[3], pmv[2])) {
1910                                                                                                    if (!
1911                                                                                                            (MotionFlags &
1912                                                                                                             PMV_HALFPEL8)) {
1913                                                                                                            pmv[3].x = EVEN(pmv[3].x);
1914                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1915                  }                  }
1916                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
1917                                                                                                                                            pmv[3].y);
1918                  }                  }
1919          }          }
1920    
1921            if ((MVzero(*currMV)) &&
1922                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1923                    iMinSAD -= MV8_00_BIAS;
1924    
1925    
1926  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1927     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.
1928  */  */
1929    
1930          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
1931                  {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1932                          if (MotionFlags & PMV_QUICKSTOP8)                   ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1933                                  goto step10_8b;                  if (MotionFlags & PMV_QUICKSTOP16)
1934                          if (MotionFlags & PMV_EARLYSTOP8)                          goto PMVfast8_Terminate_without_Refine;
1935                                  goto step10_8;                  if (MotionFlags & PMV_EARLYSTOP16)
1936                            goto PMVfast8_Terminate_with_Refine;
1937                  }                  }
1938    
1939  /************ (Diamond Search)  **************/  /************ (Diamond Search)  **************/
# Line 1150  Line 1949 
1949          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1950    
1951  /* 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 */
1952          iSAD = PMVfastSearch8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1953                  x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
1954                  currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
1955                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1956                                                      iQuant, iFound);
1957    
1958          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1959                  *currMV = newMV;                  *currMV = newMV;
1960                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1961          }          }
1962    
1963          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
1964  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1965    
1966                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1967                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1968                                  x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1969                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
1970                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1971                                                                      iDiamondSize, iFcode, iQuant, iFound);
1972    
1973                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
1974                                  *currMV = newMV;                                  *currMV = newMV;
1975                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
1976                          }                          }
1977                  }                  }
1978    
1979                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1980                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1981                                  x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1982                          0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
1983                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
1984                                                                      iQuant, iFound);
1985    
1986                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
1987                                  *currMV = newMV;                                  *currMV = newMV;
1988                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
1989                          }                          }
# Line 1196  Line 1994 
1994           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.
1995  */  */
1996    
1997  step10_8:    PMVfast8_Terminate_with_Refine:
1998          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1999                  iMinSAD = PMVfastSearch8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2000                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2001                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2002                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2003    
2004    
2005      PMVfast8_Terminate_without_Refine:
2006            currPMV->x = currMV->x - center_x;
2007            currPMV->y = currMV->y - center_y;
2008    
2009            return iMinSAD;
2010    }
2011    
2012    int32_t
2013    EPZSSearch16(const uint8_t * const pRef,
2014                             const uint8_t * const pRefH,
2015                             const uint8_t * const pRefV,
2016                             const uint8_t * const pRefHV,
2017                             const IMAGE * const pCur,
2018                             const int x,
2019                             const int y,
2020                            const int start_x,
2021                            const int start_y,
2022                            const int center_x,
2023                            const int center_y,
2024                             const uint32_t MotionFlags,
2025                             const uint32_t iQuant,
2026                             const uint32_t iFcode,
2027                             const MBParam * const pParam,
2028                             const MACROBLOCK * const pMBs,
2029                             const MACROBLOCK * const prevMBs,
2030                             VECTOR * const currMV,
2031                             VECTOR * const currPMV)
2032    {
2033            const uint32_t iWcount = pParam->mb_width;
2034            const uint32_t iHcount = pParam->mb_height;
2035    
2036            const int32_t iWidth = pParam->width;
2037            const int32_t iHeight = pParam->height;
2038            const int32_t iEdgedWidth = pParam->edged_width;
2039    
2040            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2041    
2042            int32_t min_dx;
2043            int32_t max_dx;
2044            int32_t min_dy;
2045            int32_t max_dy;
2046    
2047            VECTOR newMV;
2048            VECTOR backupMV;
2049    
2050            VECTOR pmv[4];
2051            int32_t psad[8];
2052    
2053            static MACROBLOCK *oldMBs = NULL;
2054    
2055    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2056            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2057            MACROBLOCK *oldMB = NULL;
2058    
2059             int32_t thresh2;
2060            int32_t bPredEq;
2061            int32_t iMinSAD, iSAD = 9999;
2062    
2063            MainSearch16FuncPtr MainSearchPtr;
2064    
2065            if (oldMBs == NULL) {
2066                    oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2067    //      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2068            }
2069            oldMB = oldMBs + x + y * iWcount;
2070    
2071    /* Get maximum range */
2072            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2073                              iFcode);
2074    
2075            if (!(MotionFlags & PMV_HALFPEL16)) {
2076                    min_dx = EVEN(min_dx);
2077                    max_dx = EVEN(max_dx);
2078                    min_dy = EVEN(min_dy);
2079                    max_dy = EVEN(max_dy);
2080            }
2081            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2082            //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2083            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2084    
2085    /* Step 4: Calculate SAD around the Median prediction.
2086            MinSAD=SAD
2087            If Motion Vector equal to Previous frame motion vector
2088                    and MinSAD<PrevFrmSAD goto Step 10.
2089            If SAD<=256 goto Step 10.
2090    */
2091    
2092    // Prepare for main loop
2093    
2094            currMV->x = start_x;
2095            currMV->y = start_y;
2096    
2097            if (!(MotionFlags & PMV_HALFPEL16)) {
2098                    currMV->x = EVEN(currMV->x);
2099                    currMV->y = EVEN(currMV->y);
2100            }
2101    
2102            if (currMV->x > max_dx)
2103                    currMV->x = max_dx;
2104            if (currMV->x < min_dx)
2105                    currMV->x = min_dx;
2106            if (currMV->y > max_dy)
2107                    currMV->y = max_dy;
2108            if (currMV->y < min_dy)
2109                    currMV->y = min_dy;
2110    
2111    /***************** This is predictor SET A: only median prediction ******************/
2112    
2113            iMinSAD =
2114                    sad16(cur,
2115                              get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2116                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2117            iMinSAD +=
2118                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2119                                              (uint8_t) iFcode, iQuant);
2120    
2121    // thresh1 is fixed to 256
2122            if ((iMinSAD < 256) ||
2123                    ((MVequal(*currMV, prevMB->mvs[0])) &&
2124                     ((int32_t) iMinSAD < prevMB->sad16))) {
2125                    if (MotionFlags & PMV_QUICKSTOP16)
2126                            goto EPZS16_Terminate_without_Refine;
2127                    if (MotionFlags & PMV_EARLYSTOP16)
2128                            goto EPZS16_Terminate_with_Refine;
2129            }
2130    
2131    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2132    
2133    // previous frame MV
2134            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
2135    
2136    // set threshhold based on Min of Prediction and SAD of collocated block
2137    // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
2138    
2139            if ((x == 0) && (y == 0)) {
2140                    thresh2 = 512;
2141            } else {
2142    /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
2143    
2144                    thresh2 = MIN(psad[0], iSAD) * 6 / 5 + 128;
2145            }
2146    
2147    // MV=(0,0) is often a good choice
2148    
2149            CHECK_MV16_ZERO;
2150    
2151    
2152    // left neighbour, if allowed
2153            if (x != 0) {
2154                    if (!(MotionFlags & PMV_HALFPEL16)) {
2155                            pmv[1].x = EVEN(pmv[1].x);
2156                            pmv[1].y = EVEN(pmv[1].y);
2157                    }
2158                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2159            }
2160    // top neighbour, if allowed
2161            if (y != 0) {
2162                    if (!(MotionFlags & PMV_HALFPEL16)) {
2163                            pmv[2].x = EVEN(pmv[2].x);
2164                            pmv[2].y = EVEN(pmv[2].y);
2165                    }
2166                    CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2167    
2168    // top right neighbour, if allowed
2169                    if ((uint32_t) x != (iWcount - 1)) {
2170                            if (!(MotionFlags & PMV_HALFPEL16)) {
2171                                    pmv[3].x = EVEN(pmv[3].x);
2172                                    pmv[3].y = EVEN(pmv[3].y);
2173                            }
2174                            CHECK_MV16_CANDIDATE(pmv[3].x, pmv[3].y);
2175                    }
2176            }
2177    
2178    /* Terminate if MinSAD <= T_2
2179       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2180    */
2181    
2182            if ((iMinSAD <= thresh2)
2183                    || (MVequal(*currMV, prevMB->mvs[0]) &&
2184                            ((int32_t) iMinSAD <= prevMB->sad16))) {
2185                    if (MotionFlags & PMV_QUICKSTOP16)
2186                            goto EPZS16_Terminate_without_Refine;
2187                    if (MotionFlags & PMV_EARLYSTOP16)
2188                            goto EPZS16_Terminate_with_Refine;
2189            }
2190    
2191    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
2192    
2193            backupMV = prevMB->mvs[0];      // collocated MV
2194            backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2195            backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2196    
2197            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y);
2198    
2199    // left neighbour
2200            if (x != 0)
2201                    CHECK_MV16_CANDIDATE((prevMB - 1)->mvs[0].x, (prevMB - 1)->mvs[0].y);
2202    
2203    // top neighbour
2204            if (y != 0)
2205                    CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2206                                                             (prevMB - iWcount)->mvs[0].y);
2207    
2208    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2209    
2210  step10_8b:          if ((uint32_t) x != iWcount - 1)
2211                    CHECK_MV16_CANDIDATE((prevMB + 1)->mvs[0].x, (prevMB + 1)->mvs[0].y);
2212    
2213          currPMV->x = currMV->x - pmv[0].x;  // bottom neighbour, dito
2214          currPMV->y = currMV->y - pmv[0].y;          if ((uint32_t) y != iHcount - 1)
2215                    CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2216                                                             (prevMB + iWcount)->mvs[0].y);
2217    
2218    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2219            if (iMinSAD <= thresh2) {
2220                    if (MotionFlags & PMV_QUICKSTOP16)
2221                            goto EPZS16_Terminate_without_Refine;
2222                    if (MotionFlags & PMV_EARLYSTOP16)
2223                            goto EPZS16_Terminate_with_Refine;
2224            }
2225    
2226    /************ (if Diamond Search)  **************/
2227    
2228            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2229    
2230            if (MotionFlags & PMV_USESQUARES16)
2231                    MainSearchPtr = Square16_MainSearch;
2232            else
2233             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2234                    MainSearchPtr = AdvDiamond16_MainSearch;
2235            else
2236                    MainSearchPtr = Diamond16_MainSearch;
2237    
2238    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2239    
2240            iSAD =
2241                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2242                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2243                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2244    
2245            if (iSAD < iMinSAD) {
2246                    *currMV = newMV;
2247                    iMinSAD = iSAD;
2248            }
2249    
2250    
2251            if (MotionFlags & PMV_EXTSEARCH16) {
2252    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2253    
2254                    if (!(MVequal(pmv[0], backupMV))) {
2255                            iSAD =
2256                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2257                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2258                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2259                                                                      2, iFcode, iQuant, 0);
2260                    }
2261    
2262                    if (iSAD < iMinSAD) {
2263                            *currMV = newMV;
2264                            iMinSAD = iSAD;
2265                    }
2266    
2267                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2268                            iSAD =
2269                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2270                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2271                                                                      max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2272    
2273                            if (iSAD < iMinSAD) {
2274                                    *currMV = newMV;
2275                                    iMinSAD = iSAD;
2276                            }
2277                    }
2278            }
2279    
2280    /***************        Choose best MV found     **************/
2281    
2282      EPZS16_Terminate_with_Refine:
2283            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2284                    iMinSAD =
2285                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2286                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2287                                                             iFcode, iQuant, iEdgedWidth);
2288    
2289      EPZS16_Terminate_without_Refine:
2290    
2291            *oldMB = *prevMB;
2292    
2293            currPMV->x = currMV->x - center_x;
2294            currPMV->y = currMV->y - center_y;
2295          return iMinSAD;          return iMinSAD;
2296  }  }
2297    
2298    
2299    int32_t
2300    EPZSSearch8(const uint8_t * const pRef,
2301                            const uint8_t * const pRefH,
2302                            const uint8_t * const pRefV,
2303                            const uint8_t * const pRefHV,
2304                            const IMAGE * const pCur,
2305                            const int x,
2306                            const int y,
2307                            const int start_x,
2308                            const int start_y,
2309                            const int center_x,
2310                            const int center_y,
2311                            const uint32_t MotionFlags,
2312                            const uint32_t iQuant,
2313                            const uint32_t iFcode,
2314                            const MBParam * const pParam,
2315                            const MACROBLOCK * const pMBs,
2316                            const MACROBLOCK * const prevMBs,
2317                            VECTOR * const currMV,
2318                            VECTOR * const currPMV)
2319    {
2320    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
2321    
2322            const uint32_t iWcount = pParam->mb_width;
2323            const int32_t iWidth = pParam->width;
2324            const int32_t iHeight = pParam->height;
2325            const int32_t iEdgedWidth = pParam->edged_width;
2326    
2327            const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;
2328    
2329            int32_t iDiamondSize = 1;
2330    
2331            int32_t min_dx;
2332            int32_t max_dx;
2333            int32_t min_dy;
2334            int32_t max_dy;
2335    
2336            VECTOR newMV;
2337            VECTOR backupMV;
2338    
2339            VECTOR pmv[4];
2340            int32_t psad[8];
2341    
2342            const int32_t iSubBlock = ((y & 1) << 1) + (x & 1);
2343    
2344    //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2345            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2346    
2347            int32_t bPredEq;
2348            int32_t iMinSAD, iSAD = 9999;
2349    
2350            MainSearch8FuncPtr MainSearchPtr;
2351    
2352    /* Get maximum range */
2353            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2354                              iFcode);
2355    
2356    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2357    
2358            if (!(MotionFlags & PMV_HALFPEL8)) {
2359                    min_dx = EVEN(min_dx);
2360                    max_dx = EVEN(max_dx);
2361                    min_dy = EVEN(min_dy);
2362                    max_dy = EVEN(max_dy);
2363            }
2364            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2365            //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv[0].x, pmv[0].y, psad);
2366            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2367    
2368    
2369    /* Step 4: Calculate SAD around the Median prediction.
2370            MinSAD=SAD
2371            If Motion Vector equal to Previous frame motion vector
2372                    and MinSAD<PrevFrmSAD goto Step 10.
2373            If SAD<=256 goto Step 10.
2374    */
2375    
2376    // Prepare for main loop
2377    
2378    
2379            if (!(MotionFlags & PMV_HALFPEL8)) {
2380                    currMV->x = EVEN(currMV->x);
2381                    currMV->y = EVEN(currMV->y);
2382            }
2383    
2384            if (currMV->x > max_dx)
2385                    currMV->x = max_dx;
2386            if (currMV->x < min_dx)
2387                    currMV->x = min_dx;
2388            if (currMV->y > max_dy)
2389                    currMV->y = max_dy;
2390            if (currMV->y < min_dy)
2391                    currMV->y = min_dy;
2392    
2393    /***************** This is predictor SET A: only median prediction ******************/
2394    
2395    
2396            iMinSAD =
2397                    sad8(cur,
2398                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2399                                                    iEdgedWidth), iEdgedWidth);
2400            iMinSAD +=
2401                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2402                                             (uint8_t) iFcode, iQuant);
2403    
2404    
2405    // thresh1 is fixed to 256
2406            if (iMinSAD < 256 / 4) {
2407                    if (MotionFlags & PMV_QUICKSTOP8)
2408                            goto EPZS8_Terminate_without_Refine;
2409                    if (MotionFlags & PMV_EARLYSTOP8)
2410                            goto EPZS8_Terminate_with_Refine;
2411            }
2412    
2413    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2414    
2415    
2416    // MV=(0,0) is often a good choice
2417            CHECK_MV8_ZERO;
2418    
2419    // previous frame MV
2420            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2421    
2422    // left neighbour, if allowed
2423            if (psad[1] != MV_MAX_ERROR) {
2424                    if (!(MotionFlags & PMV_HALFPEL8)) {
2425                            pmv[1].x = EVEN(pmv[1].x);
2426                            pmv[1].y = EVEN(pmv[1].y);
2427                    }
2428                    CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2429            }
2430    // top neighbour, if allowed
2431            if (psad[2] != MV_MAX_ERROR) {
2432                    if (!(MotionFlags & PMV_HALFPEL8)) {
2433                            pmv[2].x = EVEN(pmv[2].x);
2434                            pmv[2].y = EVEN(pmv[2].y);
2435                    }
2436                    CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2437    
2438    // top right neighbour, if allowed
2439                    if (psad[3] != MV_MAX_ERROR) {
2440                            if (!(MotionFlags & PMV_HALFPEL8)) {
2441                                    pmv[3].x = EVEN(pmv[3].x);
2442                                    pmv[3].y = EVEN(pmv[3].y);
2443                            }
2444                            CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2445                    }
2446            }
2447    
2448    /*  // this bias is zero anyway, at the moment!
2449    
2450            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2451                    iMinSAD -= MV8_00_BIAS;
2452    
2453    */
2454    
2455    /* Terminate if MinSAD <= T_2
2456       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2457    */
2458    
2459            if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
2460                    if (MotionFlags & PMV_QUICKSTOP8)
2461                            goto EPZS8_Terminate_without_Refine;
2462                    if (MotionFlags & PMV_EARLYSTOP8)
2463                            goto EPZS8_Terminate_with_Refine;
2464            }
2465    
2466    /************ (Diamond Search)  **************/
2467    
2468            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2469    
2470            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2471                    iDiamondSize *= 2;
2472    
2473    /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2474    
2475    // there is no EPZS^2 for inter4v at the moment
2476    
2477    //  if (MotionFlags & PMV_USESQUARES8)
2478    //      MainSearchPtr = Square8_MainSearch;
2479    //  else
2480    
2481            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2482                    MainSearchPtr = AdvDiamond8_MainSearch;
2483            else
2484                    MainSearchPtr = Diamond8_MainSearch;
2485    
2486            iSAD =
2487                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2488                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2489                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2490                                                      iQuant, 0);
2491    
2492    
2493            if (iSAD < iMinSAD) {
2494                    *currMV = newMV;
2495                    iMinSAD = iSAD;
2496            }
2497    
2498            if (MotionFlags & PMV_EXTSEARCH8) {
2499    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2500    
2501                    if (!(MVequal(pmv[0], backupMV))) {
2502                            iSAD =
2503                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2504                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2505                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2506                                                                      iDiamondSize, iFcode, iQuant, 0);
2507    
2508                            if (iSAD < iMinSAD) {
2509                                    *currMV = newMV;
2510                                    iMinSAD = iSAD;
2511                            }
2512                    }
2513    
2514                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2515                            iSAD =
2516                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2517                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2518                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
2519                                                                      iQuant, 0);
2520    
2521                            if (iSAD < iMinSAD) {
2522                                    *currMV = newMV;
2523                                    iMinSAD = iSAD;
2524                            }
2525                    }
2526            }
2527    
2528    /***************        Choose best MV found     **************/
2529    
2530      EPZS8_Terminate_with_Refine:
2531            if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2532                    iMinSAD =
2533                            Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2534                                                            iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2535                                                            iFcode, iQuant, iEdgedWidth);
2536    
2537      EPZS8_Terminate_without_Refine:
2538    
2539            currPMV->x = currMV->x - center_x;
2540            currPMV->y = currMV->y - center_y;
2541            return iMinSAD;
2542    }
2543    
2544    
2545    
2546    int32_t
2547    PMVfastIntSearch16(const uint8_t * const pRef,
2548                                    const uint8_t * const pRefH,
2549                                    const uint8_t * const pRefV,
2550                                    const uint8_t * const pRefHV,
2551                                    const IMAGE * const pCur,
2552                                    const int x,
2553                                    const int y,
2554                            const int start_x,
2555                            const int start_y,
2556                            const int center_x,
2557                            const int center_y,
2558                                    const uint32_t MotionFlags,
2559                                    const uint32_t iQuant,
2560                                    const uint32_t iFcode,
2561                                    const MBParam * const pParam,
2562                                    const MACROBLOCK * const pMBs,
2563                                    const MACROBLOCK * const prevMBs,
2564                                    VECTOR * const currMV,
2565                                    VECTOR * const currPMV)
2566    {
2567            const uint32_t iWcount = pParam->mb_width;
2568            const int32_t iWidth = pParam->width;
2569            const int32_t iHeight = pParam->height;
2570            const int32_t iEdgedWidth = pParam->edged_width;
2571    
2572            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2573            const VECTOR zeroMV = { 0, 0 };
2574    
2575            int32_t iDiamondSize;
2576    
2577            int32_t min_dx;
2578            int32_t max_dx;
2579            int32_t min_dy;
2580            int32_t max_dy;
2581    
2582            int32_t iFound;
2583    
2584            VECTOR newMV;
2585            VECTOR backupMV;                        /* just for PMVFAST */
2586    
2587            VECTOR pmv[4];
2588            int32_t psad[4];
2589    
2590            MainSearch16FuncPtr MainSearchPtr;
2591    
2592            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2593            MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2594    
2595            int32_t threshA, threshB;
2596            int32_t bPredEq;
2597            int32_t iMinSAD, iSAD;
2598    
2599    
2600    /* Get maximum range */
2601            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2602                              iFcode);
2603    
2604    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2605    
2606            if ((x == 0) && (y == 0)) {
2607                    threshA = 512;
2608                    threshB = 1024;
2609    
2610                    bPredEq = 0;
2611                    psad[0] = psad[1] = psad[2] = psad[3] = 0;
2612                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2613    
2614            } else {
2615                    threshA = psad[0];
2616                    threshB = threshA + 256;
2617                    if (threshA < 512)
2618                            threshA = 512;
2619                    if (threshA > 1024)
2620                            threshA = 1024;
2621                    if (threshB > 1792)
2622                            threshB = 1792;
2623    
2624                    bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2625                    *currMV = pmv[0];                       /* current best := prediction */
2626            }
2627    
2628            iFound = 0;
2629    
2630    /* Step 4: Calculate SAD around the Median prediction.
2631       MinSAD=SAD
2632       If Motion Vector equal to Previous frame motion vector
2633       and MinSAD<PrevFrmSAD goto Step 10.
2634       If SAD<=256 goto Step 10.
2635    */
2636    
2637            if (currMV->x > max_dx) {
2638                    currMV->x = EVEN(max_dx);
2639            }
2640            if (currMV->x < min_dx) {
2641                    currMV->x = EVEN(min_dx);
2642            }
2643            if (currMV->y > max_dy) {
2644                    currMV->y = EVEN(max_dy);
2645            }
2646            if (currMV->y < min_dy) {
2647                    currMV->y = EVEN(min_dy);
2648            }
2649    
2650            iMinSAD =
2651                    sad16(cur,
2652                              get_iref_mv(pRef, x, y, 16, currMV,
2653                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2654            iMinSAD +=
2655                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2656                                              (uint8_t) iFcode, iQuant);
2657    
2658            if ((iMinSAD < 256) ||
2659                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2660                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2661                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
2662                    {
2663                            if (!MVzero(*currMV)) {
2664                                    iMinSAD += MV16_00_BIAS;
2665                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2666                                    iMinSAD -= MV16_00_BIAS;
2667                            }
2668                    }
2669    
2670                    if (MotionFlags & PMV_EARLYSTOP16)
2671                            goto PMVfastInt16_Terminate_with_Refine;
2672            }
2673    
2674    
2675    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2676       vector of the median.
2677       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2678    */
2679    
2680            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2681                    iFound = 2;
2682    
2683    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2684       Otherwise select large Diamond Search.
2685    */
2686    
2687            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2688                    iDiamondSize = 2;               // halfpel units!
2689            else
2690                    iDiamondSize = 4;               // halfpel units!
2691    
2692    /*
2693       Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2694       Also calculate (0,0) but do not subtract offset.
2695       Let MinSAD be the smallest SAD up to this point.
2696       If MV is (0,0) subtract offset.
2697    */
2698    
2699    // (0,0) is often a good choice
2700    
2701            if (!MVzero(pmv[0]))
2702                    CHECK_MV16_ZERO;
2703    
2704    // previous frame MV is always possible
2705    
2706            if (!MVzero(prevMB->i_mvs[0]))
2707                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2708                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2709    
2710    // left neighbour, if allowed
2711    
2712            if (!MVzero(pmv[1]))
2713                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2714                            if (!MVequal(pmv[1], pmv[0]))
2715                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2716    
2717    // top neighbour, if allowed
2718            if (!MVzero(pmv[2]))
2719                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
2720                            if (!MVequal(pmv[2], pmv[0]))
2721                                    if (!MVequal(pmv[2], pmv[1]))
2722                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2723    
2724    // top right neighbour, if allowed
2725                                            if (!MVzero(pmv[3]))
2726                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
2727                                                            if (!MVequal(pmv[3], pmv[0]))
2728                                                                    if (!MVequal(pmv[3], pmv[1]))
2729                                                                            if (!MVequal(pmv[3], pmv[2]))
2730                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
2731                                                                                                                             pmv[3].y);
2732    
2733            if ((MVzero(*currMV)) &&
2734                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2735                    iMinSAD -= MV16_00_BIAS;
2736    
2737    
2738    /* Step 6: If MinSAD <= thresa goto Step 10.
2739       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2740    */
2741    
2742            if ((iMinSAD <= threshA) ||
2743                    (MVequal(*currMV, prevMB->i_mvs[0]) &&
2744                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2745    
2746                    if (MotionFlags & PMV_EARLYSTOP16)
2747                            goto PMVfastInt16_Terminate_with_Refine;
2748            }
2749    
2750    
2751    /************ (Diamond Search)  **************/
2752    /*
2753       Step 7: Perform Diamond search, with either the small or large diamond.
2754       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
2755       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
2756       If center then goto step 10.
2757       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
2758       Refine by using small diamond and goto step 10.
2759    */
2760    
2761            if (MotionFlags & PMV_USESQUARES16)
2762                    MainSearchPtr = Square16_MainSearch;
2763            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2764                    MainSearchPtr = AdvDiamond16_MainSearch;
2765            else
2766                    MainSearchPtr = Diamond16_MainSearch;
2767    
2768            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2769    
2770    
2771    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2772            iSAD =
2773                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2774                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2775                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2776                                                      iQuant, iFound);
2777    
2778            if (iSAD < iMinSAD) {
2779                    *currMV = newMV;
2780                    iMinSAD = iSAD;
2781            }
2782    
2783            if (MotionFlags & PMV_EXTSEARCH16) {
2784    /* extended: search (up to) two more times: orignal prediction and (0,0) */
2785    
2786                    if (!(MVequal(pmv[0], backupMV))) {
2787                            iSAD =
2788                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2789                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2790                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2791                                                                      iDiamondSize, iFcode, iQuant, iFound);
2792    
2793                            if (iSAD < iMinSAD) {
2794                                    *currMV = newMV;
2795                                    iMinSAD = iSAD;
2796                            }
2797                    }
2798    
2799                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2800                            iSAD =
2801                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2802                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2803                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
2804                                                                      iQuant, iFound);
2805    
2806                            if (iSAD < iMinSAD) {
2807                                    *currMV = newMV;
2808                                    iMinSAD = iSAD;
2809                            }
2810                    }
2811            }
2812    
2813    /*
2814       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
2815    */
2816    
2817    PMVfastInt16_Terminate_with_Refine:
2818    
2819            pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
2820            pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
2821    
2822            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2823                    iMinSAD =
2824                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2825                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2826                                                             iFcode, iQuant, iEdgedWidth);
2827    
2828            pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
2829    
2830    PMVfastInt16_Terminate_without_Refine:
2831            currPMV->x = currMV->x - center_x;
2832            currPMV->y = currMV->y - center_y;
2833            return iMinSAD;
2834    }
2835    
2836    
2837    
2838    /* ***********************************************************
2839            bvop motion estimation
2840    // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
2841    ***************************************************************/
2842    
2843    
2844    #define DIRECT_PENALTY 0
2845    #define DIRECT_UPPERLIMIT 256   // never use direct mode if SAD is larger than this
2846    
2847    void
2848    MotionEstimationBVOP(MBParam * const pParam,
2849                                             FRAMEINFO * const frame,
2850                                             const int32_t time_bp,
2851                                             const int32_t time_pp,
2852                                             // forward (past) reference
2853                                             const MACROBLOCK * const f_mbs,
2854                                             const IMAGE * const f_ref,
2855                                             const IMAGE * const f_refH,
2856                                             const IMAGE * const f_refV,
2857                                             const IMAGE * const f_refHV,
2858                                             // backward (future) reference
2859                                             const MACROBLOCK * const b_mbs,
2860                                             const IMAGE * const b_ref,
2861                                             const IMAGE * const b_refH,
2862                                             const IMAGE * const b_refV,
2863                                             const IMAGE * const b_refHV)
2864    {
2865            const int mb_width = pParam->mb_width;
2866            const int mb_height = pParam->mb_height;
2867            const int edged_width = pParam->edged_width;
2868    
2869            int i, j, k;
2870    
2871            static const VECTOR zeroMV={0,0};
2872    
2873            int f_sad16;    /* forward (as usual) search */
2874            int b_sad16;    /* backward (only in b-frames) search */
2875            int i_sad16;    /* interpolated (both direction, b-frames only) */
2876            int d_sad16;    /* direct mode (assume linear motion) */
2877    
2878            int best_sad;
2879    
2880            VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
2881            VECTOR pmv_dontcare;
2882    
2883            int f_count=0;
2884            int b_count=0;
2885            int i_count=0;
2886            int d_count=0;
2887            int s_count=0;
2888    
2889            const int64_t TRB = (int32_t)time_pp - (int32_t)time_bp;
2890        const int64_t TRD = (int32_t)time_pp;
2891    
2892            // fprintf(stderr,"TRB = %lld  TRD = %lld  time_bp =%d time_pp =%d\n\n",TRB,TRD,time_bp,time_pp);
2893            // note: i==horizontal, j==vertical
2894            for (j = 0; j < mb_height; j++) {
2895    
2896                    f_predMV = zeroMV;      /* prediction is reset at left boundary */
2897                    b_predMV = zeroMV;
2898    
2899                    for (i = 0; i < mb_width; i++) {
2900                            MACROBLOCK *mb = &frame->mbs[i + j * mb_width];
2901                            const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width];
2902                            const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width];
2903    
2904                            mb->deltamv=zeroMV;
2905    
2906    /* special case, if collocated block is SKIPed: encoding is forward(0,0)  */
2907    
2908    #ifndef _DISABLE_SKIP
2909                            if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
2910                                    b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {
2911                                    mb->mode = MODE_NOT_CODED;
2912                                    mb->mvs[0].x = 0;
2913                                    mb->mvs[0].y = 0;
2914                                    mb->b_mvs[0].x = 0;
2915                                    mb->b_mvs[0].y = 0;
2916                                    continue;
2917                            }
2918    #endif
2919    
2920                            d_sad16 = DIRECT_PENALTY;
2921    
2922                            if (b_mb->mode == MODE_INTER4V)
2923                            {
2924    
2925                            /* same method of scaling as in decoder.c, so we copy from there */
2926                        for (k = 0; k < 4; k++) {
2927    
2928                                            mb->directmv[k] = b_mb->mvs[k];
2929    
2930                                            mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
2931                        mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
2932                                                                                    ? ((TRB - TRD) * mb->directmv[k].x) / TRD
2933                                                : mb->mvs[k].x - mb->directmv[k].x);
2934    
2935                        mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
2936                            mb->b_mvs[k].y = (int32_t) ((mb->directmv[k].y == 0)
2937                                                                                    ? ((TRB - TRD) * mb->directmv[k].y) / TRD
2938                                                : mb->mvs[k].y - mb->directmv[k].y);
2939    
2940                                            d_sad16 +=
2941                                                    sad8bi(frame->image.y + 2*(i+(k&1))*8 + 2*(j+(k>>1))*8*edged_width,
2942                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2943                                                                    2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->mvs[k], edged_width),
2944                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2945                                                                    2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->b_mvs[k], edged_width),
2946                                                      edged_width);
2947                                    }
2948                            }
2949                            else
2950                            {
2951                                    mb->directmv[3] = mb->directmv[2] = mb->directmv[1] =
2952                                    mb->directmv[0] = b_mb->mvs[0];
2953    
2954                                    mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
2955                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
2956                                                                            ? ((TRB - TRD) * mb->directmv[0].x) / TRD
2957                                        : mb->mvs[0].x - mb->directmv[0].x);
2958    
2959                        mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
2960                    mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
2961                                                                            ? ((TRB - TRD) * mb->directmv[0].y) / TRD
2962                                        : mb->mvs[0].y - mb->directmv[0].y);
2963    
2964                                    d_sad16 += sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
2965                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2966                                                                    i, j, 16, &mb->mvs[0], edged_width),
2967                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2968                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
2969                                                      edged_width);
2970    
2971                }
2972                        d_sad16 += calc_delta_16(mb->deltamv.x, mb->deltamv.y, 1, frame->quant);
2973    
2974                            // forward search
2975                            f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2976                                                    &frame->image, i, j,
2977                                                    mb->mvs[0].x, mb->mvs[0].y,                     /* start point f_directMV */
2978                                                    f_predMV.x, f_predMV.y,                         /* center is f-prediction */
2979                                                    frame->motion_flags,
2980                                                    frame->quant, frame->fcode, pParam,
2981                                                    f_mbs, f_mbs,
2982                                                    &mb->mvs[0], &pmv_dontcare);
2983    
2984    
2985                            // backward search
2986                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2987                                                    &frame->image, i, j,
2988                                                    mb->b_mvs[0].x, mb->b_mvs[0].y,         /* start point b_directMV */
2989                                                    b_predMV.x, b_predMV.y,                         /* center is b-prediction */
2990                                                    frame->motion_flags,
2991                                                    frame->quant, frame->bcode, pParam,
2992                                                    b_mbs, b_mbs,
2993                                                    &mb->b_mvs[0], &pmv_dontcare);
2994    
2995                            i_sad16 =
2996                                    sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
2997                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2998                                                                    i, j, 16, &mb->mvs[0], edged_width),
2999                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3000                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
3001                                                      edged_width);
3002                        i_sad16 += calc_delta_16(mb->mvs[0].x-f_predMV.x, mb->mvs[0].y-f_predMV.y,
3003                                                                    frame->fcode, frame->quant);
3004                        i_sad16 += calc_delta_16(mb->b_mvs[0].x-b_predMV.x, mb->b_mvs[0].y-b_predMV.y,
3005                                                                    frame->bcode, frame->quant);
3006    
3007                            // TODO: direct search
3008                            // predictor + delta vector in range [-32,32] (fcode=1)
3009    
3010                            i_sad16 = 65535;
3011                            f_sad16 = 65535;
3012                            b_sad16 = 65535;
3013    //                      d_sad16 = 65535;
3014    
3015                            if (f_sad16 < b_sad16) {
3016                                    best_sad = f_sad16;
3017                                    mb->mode = MODE_FORWARD;
3018                            } else {
3019                                    best_sad = b_sad16;
3020                                    mb->mode = MODE_BACKWARD;
3021                            }
3022    
3023                            if (i_sad16 < best_sad) {
3024                                    best_sad = i_sad16;
3025                                    mb->mode = MODE_INTERPOLATE;
3026                            }
3027    
3028                            if (d_sad16 < best_sad) {
3029    
3030                                    if (b_mb->mode == MODE_INTER4V)
3031                                    {
3032    
3033                                    /* same method of scaling as in decoder.c, so we copy from there */
3034                                for (k = 0; k < 4; k++) {
3035    
3036                                                    mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3037                                mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3038                                                                                            ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3039                                                        : mb->mvs[k].x - mb->directmv[k].x);
3040    
3041                                mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3042                            mb->b_mvs[k].y = (int32_t) ((mb->directmv[k].y == 0)
3043                                                                                            ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3044                                                : mb->mvs[k].y - mb->directmv[k].y);
3045                                            }
3046                                    }
3047                                    else
3048                                    {
3049                                            mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3050    
3051                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3052                                                                                    ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3053                                            : mb->mvs[0].x - mb->directmv[0].x);
3054    
3055                                mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3056    
3057                            mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
3058                                                                                    ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3059                                                : mb->mvs[0].y - mb->directmv[0].y);
3060    
3061                                            mb->mvs[3] = mb->mvs[2] = mb->mvs[1] = mb->mvs[0];
3062                                            mb->b_mvs[3] = mb->b_mvs[2] = mb->b_mvs[1] = mb->b_mvs[0];
3063                    }
3064    
3065                                    best_sad = d_sad16;
3066                                    mb->mode = MODE_DIRECT;
3067                                    mb->mode = MODE_INTERPOLATE;            // direct mode still broken :-(
3068                            }
3069    
3070                            switch (mb->mode)
3071                            {
3072                                    case MODE_FORWARD:
3073                                            f_count++;
3074                                            f_predMV = mb->mvs[0];
3075                                            break;
3076                                    case MODE_BACKWARD:
3077                                            b_count++;
3078                                            b_predMV = mb->b_mvs[0];
3079    
3080                                            break;
3081                                    case MODE_INTERPOLATE:
3082                                            i_count++;
3083                                            f_predMV = mb->mvs[0];
3084                                            b_predMV = mb->b_mvs[0];
3085                                            break;
3086                                    case MODE_DIRECT:
3087                                            d_count++;
3088                                            break;
3089                                    default:
3090                                            s_count++;              // ???
3091                                            break;
3092                            }
3093    
3094                    }
3095            }
3096    
3097    #ifdef _DEBUG_BFRAME_STAT
3098            fprintf(stderr,"B-Stat: F: %04d   B: %04d   I: %04d  D: %04d   S: %04d\n",
3099                                    f_count,b_count,i_count,d_count,s_count);
3100    #endif
3101    
3102    }

Legend:
Removed from v.3  
changed lines
  Added in v.344

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