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

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

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

revision 3, Fri Mar 8 02:46:11 2002 UTC revision 152, Wed May 1 13:00:02 2002 UTC
# Line 2  Line 2 
2   *   *
3   *  Modifications:   *  Modifications:
4   *   *
5     *      01.05.2002      updated MotionEstimationBVOP
6     *      25.04.2002 partial prevMB conversion
7     *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>
8     *  14.04.2002 added MotionEstimationBVOP()
9     *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between
10     *             EPZS and EPZS^2
11   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop
12   *             PMVFast_Refine to support multiple searches with different start points   *             PMVFast_Refine to support multiple searches with different start points
13   *      07.01.2002 uv-block-based interpolation   *      07.01.2002 uv-block-based interpolation
# Line 31  Line 37 
37    
38  #include <assert.h>  #include <assert.h>
39  #include <stdio.h>  #include <stdio.h>
40    #include <stdlib.h>
41    
42  #include "../encoder.h"  #include "../encoder.h"
43  #include "../utils/mbfunctions.h"  #include "../utils/mbfunctions.h"
44  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
45  #include "../global.h"  #include "../global.h"
46  #include "../utils/timer.h"  #include "../utils/timer.h"
47    #include "motion.h"
48  #include "sad.h"  #include "sad.h"
49    
50  // very large value  // very large value
# Line 49  Line 57 
57  /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */
58  /* nb  = vop pixels * 2^(bpp-8) */  /* nb  = vop pixels * 2^(bpp-8) */
59  #define MV16_00_BIAS    (128+1)  #define MV16_00_BIAS    (128+1)
60    #define MV8_00_BIAS     (0)
61    
62  /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */  /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */
63  #define INTER_BIAS      512  #define INTER_BIAS      512
# Line 65  Line 74 
74  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)
75    
76    
77  #define MIN(X, Y) ((X)<(Y)?(X):(Y))  int32_t PMVfastSearch16(
78  #define MAX(X, Y) ((X)>(Y)?(X):(Y))                                          const uint8_t * const pRef,
79  #define ABS(X) (((X)>0)?(X):-(X))                                          const uint8_t * const pRefH,
80  #define SIGN(X) (((X)>0)?1:-1)                                          const uint8_t * const pRefV,
81                                            const uint8_t * const pRefHV,
82                                            const IMAGE * const pCur,
83                                            const int x, const int y,
84                                            const uint32_t MotionFlags,
85                                            const uint32_t iQuant,
86                                            const uint32_t iFcode,
87                                            const MBParam * const pParam,
88                                            const MACROBLOCK * const pMBs,
89                                            const MACROBLOCK * const prevMBs,
90                                            VECTOR * const currMV,
91                                            VECTOR * const currPMV);
92    
93    int32_t EPZSSearch16(
94                                            const uint8_t * const pRef,
95                                            const uint8_t * const pRefH,
96                                            const uint8_t * const pRefV,
97                                            const uint8_t * const pRefHV,
98                                            const IMAGE * const pCur,
99                                            const int x, const int y,
100                                            const uint32_t MotionFlags,
101                                            const uint32_t iQuant,
102                                            const uint32_t iFcode,
103                                            const MBParam * const pParam,
104                                            const MACROBLOCK * const pMBs,
105                                            const MACROBLOCK * const prevMBs,
106                                            VECTOR * const currMV,
107                                            VECTOR * const currPMV);
108    
109    
110  int32_t PMVfastSearch8(  int32_t PMVfastSearch8(
# Line 78  Line 114 
114                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
115                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
116                                          const int x, const int y,                                          const int x, const int y,
117                                          const int start_x, int start_y,                                          const int start_x, const int start_y,
118                                          const uint32_t iQuality,                                          const uint32_t MotionFlags,
119                                          MBParam * const pParam,                                          const uint32_t iQuant,
120                                          MACROBLOCK * const pMBs,                                          const uint32_t iFcode,
121                                            const MBParam * const pParam,
122                                            const MACROBLOCK * const pMBs,
123                                            const MACROBLOCK * const prevMBs,
124                                          VECTOR * const currMV,                                          VECTOR * const currMV,
125                                          VECTOR * const currPMV);                                          VECTOR * const currPMV);
126    
127  int32_t PMVfastSearch16(  int32_t EPZSSearch8(
128                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
129                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
130                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
131                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
132                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
133                                          const int x, const int y,                                          const int x, const int y,
134                                          const uint32_t iQuality,                                          const int start_x, const int start_y,
135                                          MBParam * const pParam,                                          const uint32_t MotionFlags,
136                                          MACROBLOCK * const pMBs,                                          const uint32_t iQuant,
137                                            const uint32_t iFcode,
138                                            const MBParam * const pParam,
139                                            const MACROBLOCK * const pMBs,
140                                            const MACROBLOCK * const prevMBs,
141                                          VECTOR * const currMV,                                          VECTOR * const currMV,
142                                          VECTOR * const currPMV);                                          VECTOR * const currPMV);
143    
144    
145    typedef int32_t (MainSearch16Func)(
146            const uint8_t * const pRef,
147            const uint8_t * const pRefH,
148            const uint8_t * const pRefV,
149            const uint8_t * const pRefHV,
150            const uint8_t * const cur,
151            const int x, const int y,
152            int32_t startx, int32_t starty,
153            int32_t iMinSAD,
154            VECTOR * const currMV,
155            const VECTOR * const pmv,
156            const int32_t min_dx, const int32_t max_dx,
157            const int32_t min_dy, const int32_t max_dy,
158            const int32_t iEdgedWidth,
159            const int32_t iDiamondSize,
160            const int32_t iFcode,
161            const int32_t iQuant,
162            int iFound);
163    
164  /* diamond search stuff  typedef MainSearch16Func* MainSearch16FuncPtr;
    keep the the sequence in circular order (so optimization works)  
 */  
165    
 typedef struct  
 {  
         int32_t dx;  
         int32_t dy;  
 }  
 DPOINT;  
166    
167    typedef int32_t (MainSearch8Func)(
168            const uint8_t * const pRef,
169            const uint8_t * const pRefH,
170            const uint8_t * const pRefV,
171            const uint8_t * const pRefHV,
172            const uint8_t * const cur,
173            const int x, const int y,
174            int32_t startx, int32_t starty,
175            int32_t iMinSAD,
176            VECTOR * const currMV,
177            const VECTOR * const pmv,
178            const int32_t min_dx, const int32_t max_dx,
179            const int32_t min_dy, const int32_t max_dy,
180            const int32_t iEdgedWidth,
181            const int32_t iDiamondSize,
182            const int32_t iFcode,
183            const int32_t iQuant,
184            int iFound);
185    
186  static const DPOINT diamond_small[4] =  typedef MainSearch8Func* MainSearch8FuncPtr;
 {  
         {0, 1}, {1, 0}, {0, -1}, {-1, 0}  
 };  
187    
188    static int32_t lambda_vec16[32] =  /* rounded values for lambda param for weight of motion bits as in modified H.26L */
189            {     0    ,(int)(1.00235+0.5), (int)(1.15582+0.5), (int)(1.31976+0.5), (int)(1.49591+0.5), (int)(1.68601+0.5),
190            (int)(1.89187+0.5), (int)(2.11542+0.5), (int)(2.35878+0.5), (int)(2.62429+0.5), (int)(2.91455+0.5),
191            (int)(3.23253+0.5), (int)(3.58158+0.5), (int)(3.96555+0.5), (int)(4.38887+0.5), (int)(4.85673+0.5),
192            (int)(5.37519+0.5), (int)(5.95144+0.5), (int)(6.59408+0.5), (int)(7.31349+0.5), (int)(8.12242+0.5),
193            (int)(9.03669+0.5), (int)(10.0763+0.5), (int)(11.2669+0.5), (int)(12.6426+0.5), (int)(14.2493+0.5),
194            (int)(16.1512+0.5), (int)(18.442+0.5),  (int)(21.2656+0.5), (int)(24.8580+0.5), (int)(29.6436+0.5),
195            (int)(36.4949+0.5)      };
196    
197    static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now*/
198    
 static const DPOINT diamond_large[8] =  
 {  
         {0, 2}, {1, 1}, {2, 0}, {1, -1}, {0, -2}, {-1, -1}, {-2, 0}, {-1, 1}  
 };  
199    
200    
201  // mv.length table  // mv.length table
# Line 159  Line 233 
233  }  }
234    
235    
236  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode)  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)
 {  
         return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));  
 }  
   
 static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)  
   
237  {  {
238      return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));          return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
239  }  }
240    
241    static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)
242    
   
   
 /* calculate the min/max range (in halfpixels)  
         relative to the _MACROBLOCK_ position  
 */  
   
 static void __inline get_range(  
                         int32_t * const min_dx, int32_t * const max_dx,  
                         int32_t * const min_dy, int32_t * const max_dy,  
                         const uint32_t x, const uint32_t y,  
                         const uint32_t block_sz,                                        // block dimension, 8 or 16  
                         const uint32_t width, const uint32_t height,  
                         const uint32_t fcode)  
243  {  {
244          const int search_range = 32 << (fcode - 1);      return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
     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));  
245  }  }
246    
247    
 /* 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;  
         }  
 }  
   
248    
 /* This is somehow a copy of get_ref, but with MV instead of X,Y */  
249    
 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;  
         }  
 }  
250    
251  #ifndef SEARCH16  #ifndef SEARCH16
252  #define SEARCH16        PMVfastSearch16  #define SEARCH16        PMVfastSearch16
253    //#define SEARCH16      FullSearch16
254    //#define SEARCH16      EPZSSearch16
255  #endif  #endif
256    
257  #ifndef SEARCH8  #ifndef SEARCH8
258  #define SEARCH8         PMVfastSearch8  #define SEARCH8         PMVfastSearch8
259    //#define SEARCH8       EPZSSearch8
260  #endif  #endif
261    
262  bool MotionEstimation(  bool MotionEstimation(
                         MACROBLOCK * const pMBs,  
263                          MBParam * const pParam,                          MBParam * const pParam,
264                      const IMAGE * const pRef,          FRAMEINFO * const current,
265            FRAMEINFO * const reference,
266                          const IMAGE * const pRefH,                          const IMAGE * const pRefH,
267                      const IMAGE * const pRefV,                      const IMAGE * const pRefV,
268                          const IMAGE * const pRefHV,                          const IMAGE * const pRefHV,
                     IMAGE * const pCurrent,  
269                          const uint32_t iLimit)                          const uint32_t iLimit)
270    
271  {  {
272      const uint32_t iWcount = pParam->mb_width;      const uint32_t iWcount = pParam->mb_width;
273      const uint32_t iHcount = pParam->mb_height;      const uint32_t iHcount = pParam->mb_height;
274            MACROBLOCK * pMBs = current->mbs;
275            IMAGE * pCurrent = &current->image;
276    
277            MACROBLOCK * prevMBs = reference->mbs;  // previous frame
278            IMAGE * pRef = &reference->image;
279    
280    
281          uint32_t i, j, iIntra = 0;          uint32_t i, j, iIntra = 0;
282    
# Line 282  Line 287 
287      int32_t sad16;      int32_t sad16;
288      int32_t deviation;      int32_t deviation;
289    
290            if (sadInit)
291                    (*sadInit)();
292    
293    
294            /* eventhough we have a seperate prevMBs,
295               pmvfast/epsz does something "funny" with the previous frames data */
296    
297    /*      for (i = 0; i < iHcount; i++)
298                    for (j = 0; j < iWcount; j++)
299                    {
300                            pMBs[j + i * iWcount].mvs[0] = prevMBs[j + i * iWcount].mvs[0];
301                            pMBs[j + i * iWcount].mvs[1] = prevMBs[j + i * iWcount].mvs[1];
302                            pMBs[j + i * iWcount].mvs[2] = prevMBs[j + i * iWcount].mvs[2];
303                            pMBs[j + i * iWcount].mvs[3] = prevMBs[j + i * iWcount].mvs[3];
304                    }
305    */
306            /*dprintf("*** BEFORE ***");
307            for (i = 0; i < iHcount; i++)
308                    for (j = 0; j < iWcount; j++)
309                    {
310                            dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,
311                                    pMBs[j + i * iWcount].mode,
312                                    pMBs[j + i * iWcount].dquant,
313                                    pMBs[j + i * iWcount].mvs[0],
314                                    pMBs[j + i * iWcount].mvs[1],
315                                    pMBs[j + i * iWcount].mvs[2],
316                                    pMBs[j + i * iWcount].mvs[3],
317                                    prevMBs[j + i * iWcount].sad8[0],
318                                    prevMBs[j + i * iWcount].sad8[1],
319                                    prevMBs[j + i * iWcount].sad8[2],
320                                    prevMBs[j + i * iWcount].sad8[3],
321                                    prevMBs[j + i * iWcount].sad16);
322                    }
323            */
324    
325          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
326      for (i = 0; i < iHcount; i++)      for (i = 0; i < iHcount; i++)
327                  for (j = 0; j < iWcount; j++)                  for (j = 0; j < iWcount; j++)
328                  {                  {
329                          MACROBLOCK *pMB = &pMBs[j + i * iWcount];                          MACROBLOCK *pMB = &pMBs[j + i * iWcount];
330                            MACROBLOCK *prevMB = &prevMBs[j + i * iWcount];
331    
332                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
333                                            j, i, pParam->motion_flags,                                           j, i, current->motion_flags, current->quant, current->fcode,
334                                            pParam, pMBs, &mv16, &pmv16);                                           pParam, pMBs, prevMBs, &mv16, &pmv16);
335                          pMB->sad16=sad16;                          pMB->sad16=sad16;
336    
337    
# Line 306  Line 347 
347                          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;                          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;
348                          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;
349    
350                                    pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;
351    
352                          iIntra++;                          iIntra++;
353                          if(iIntra >= iLimit)                          if(iIntra >= iLimit)
354                                  return 1;                                  return 1;
# Line 313  Line 356 
356                          continue;                          continue;
357                  }                  }
358    
359                  if (pParam->global_flags & XVID_INTER4V)                          if (current->global_flags & XVID_INTER4V)
360                  {                  {
361                          pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
362                                          2 * j, 2 * i, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j, 2 * i, mv16.x, mv16.y,
363                                          pParam, pMBs, &pMB->mvs[0], &pMB->pmvs[0]);                                                             current->motion_flags, current->quant, current->fcode,
364                                                           pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);
365    
366                          pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
367                                          2 * j + 1, 2 * i, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j + 1, 2 * i, mv16.x, mv16.y,
368                                          pParam, pMBs, &pMB->mvs[1], &pMB->pmvs[1]);                                                             current->motion_flags, current->quant, current->fcode,
369                                                           pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);
370    
371                          pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
372                                          2 * j, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j, 2 * i + 1, mv16.x, mv16.y,
373                                          pParam, pMBs, &pMB->mvs[2], &pMB->pmvs[2]);                                                             current->motion_flags, current->quant, current->fcode,
374                                                           pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);
375    
376                          pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
377                                          2 * j + 1, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j + 1, 2 * i + 1, mv16.x, mv16.y,
378                                          pParam, pMBs, &pMB->mvs[3], &pMB->pmvs[3]);                                                             current->motion_flags, current->quant, current->fcode,
379                                                           pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);
380    
381                          sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];                          sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];
382                  }                  }
# Line 339  Line 386 
386                          mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                          mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v
387                  */                  */
388    
389                  if (pMB->dquant == NO_CHANGE) {                          if (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE)
390                          if (((pParam->global_flags & XVID_INTER4V)==0) ||                          {
391                                  (sad16 < (sad8 + (int32_t)(IMV16X16 * pParam->quant)))) {                                  if (((current->global_flags & XVID_INTER4V)==0) ||
392                                        (sad16 < (sad8 + (int32_t)(IMV16X16 * current->quant))))
393                                    {
394    
395                                  sad8 = sad16;                                  sad8 = sad16;
396                                  pMB->mode = MODE_INTER;                                  pMB->mode = MODE_INTER;
# Line 364  Line 413 
413                  }                  }
414          }          }
415    
416    /*      dprintf("*** AFTER ***", pMBs[0].b_mvs[0].x);
417            for (i = 0; i < iHcount; i++)
418                    for (j = 0; j < iWcount; j++)
419                    {
420                            dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,
421                                    pMBs[j + i * iWcount].mode,
422                                    pMBs[j + i * iWcount].dquant,
423                                    pMBs[j + i * iWcount].mvs[0],
424                                    pMBs[j + i * iWcount].mvs[1],
425                                    pMBs[j + i * iWcount].mvs[2],
426                                    pMBs[j + i * iWcount].mvs[3],
427                                    pMBs[j + i * iWcount].sad8[0],
428                                    pMBs[j + i * iWcount].sad8[1],
429                                    pMBs[j + i * iWcount].sad8[2],
430                                    pMBs[j + i * iWcount].sad8[3],
431                                    pMBs[j + i * iWcount].sad16);
432                    }
433            */
434    
435          return 0;          return 0;
436  }  }
437    
# Line 377  Line 445 
445      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
446    { \    { \
447      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); \
448      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\
     if (iSAD <= iQuant * 96)    \  
         iSAD -= MV16_00_BIAS; \  
449      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
450      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
451  }  }
452    
453    #define NOCHECK_MV16_CANDIDATE(X,Y) { \
454        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
455        iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
456        if (iSAD < iMinSAD) \
457        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
458    }
459    
460  #define CHECK_MV16_CANDIDATE(X,Y) { \  #define CHECK_MV16_CANDIDATE(X,Y) { \
461    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
462      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
463    { \    { \
464      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); \
465      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
466      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
467      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
468  }  }
# Line 400  Line 472 
472      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
473    { \    { \
474      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); \
475      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
476      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
477      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
478  }  }
# Line 410  Line 482 
482      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
483    { \    { \
484      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); \
485      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
486      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
487      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
488  }  }
# Line 418  Line 490 
490    
491  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
492    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); \
493    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\
494    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
495    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
496  }  }
497    
498    #define NOCHECK_MV8_CANDIDATE(X,Y) \
499      { \
500        iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
501        iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
502        if (iSAD < iMinSAD) \
503        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
504    }
505    
506  #define CHECK_MV8_CANDIDATE(X,Y) { \  #define CHECK_MV8_CANDIDATE(X,Y) { \
507    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
508      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
509    { \    { \
510      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); \
511      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
512      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
513      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
514  }  }
# Line 439  Line 518 
518      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
519    { \    { \
520      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); \
521      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
522      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
523      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
524  }  }
# Line 449  Line 528 
528      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
529    { \    { \
530      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); \
531      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
532      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
533      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
534  }  }
# Line 464  Line 543 
543                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
544                                          const int x, const int y,                                          const int x, const int y,
545                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
546                                            const uint32_t iQuant,
547                                            const uint32_t iFcode,
548                                          MBParam * const pParam,                                          MBParam * const pParam,
549                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
550                                            const MACROBLOCK * const prevMBs,
551                                          VECTOR * const currMV,                                          VECTOR * const currMV,
552                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
553  {  {
554          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
555          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
556          int32_t iSAD;          int32_t iSAD;
557          int32_t pred_x,pred_y;          int32_t pred_x,pred_y;
# Line 493  Line 574 
574  }  }
575  */  */
576    
577  int32_t PMVfastSearch16_MainSearch(  int32_t Diamond16_MainSearch(
578                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
579                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
580                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 550  Line 631 
631          return iMinSAD;          return iMinSAD;
632  }  }
633    
634  int32_t PMVfastSearch16_Refine(  int32_t Square16_MainSearch(
635                                            const uint8_t * const pRef,
636                                            const uint8_t * const pRefH,
637                                            const uint8_t * const pRefV,
638                                            const uint8_t * const pRefHV,
639                                            const uint8_t * const cur,
640                                            const int x, const int y,
641                                            int32_t startx, int32_t starty,
642                                            int32_t iMinSAD,
643                                            VECTOR * const currMV,
644                                            const VECTOR * const pmv,
645                                            const int32_t min_dx, const int32_t max_dx,
646                                            const int32_t min_dy, const int32_t max_dy,
647                                            const int32_t iEdgedWidth,
648                                            const int32_t iDiamondSize,
649                                            const int32_t iFcode,
650                                            const int32_t iQuant,
651                                            int iFound)
652    {
653    /* Do a square search around given starting point, return SAD of best */
654    
655            int32_t iDirection=0;
656            int32_t iSAD;
657            VECTOR backupMV;
658            backupMV.x = startx;
659            backupMV.y = starty;
660    
661    /* It's one search with full square pattern, and new parts for all following diamonds */
662    
663    /*   new direction are extra, so 1-4 is normal diamond
664          537
665          1*2
666          648
667    */
668    
669            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
670            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
671            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
672            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
673    
674            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
675            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
676            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
677            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
678    
679    
680            if (iDirection)
681                    while (!iFound)
682                    {
683                            iFound = 1;
684                            backupMV=*currMV;
685    
686                            switch (iDirection)
687                            {
688                                    case 1:
689                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
690                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
691                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
692                                            break;
693                                    case 2:
694                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
695                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
696                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
697                                            break;
698    
699                                    case 3:
700                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
701                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
702                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
703                                            break;
704    
705                                    case 4:
706                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
707                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
708                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
709                                            break;
710    
711                                    case 5:
712                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
713                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
714                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
715                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
716                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
717                                            break;
718    
719                                    case 6:
720                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
721                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
722    
723                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
724                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
725                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
726    
727                                            break;
728    
729                                    case 7:
730                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
731                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
732                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
733                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
734                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
735                                            break;
736    
737                                    case 8:
738                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
739                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
740                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
741                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
742                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
743                                            break;
744                            default:
745                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
746                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
747                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
748                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
749    
750                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
751                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
752                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
753                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
754                                            break;
755                            }
756                    }
757            else
758                    {
759                            currMV->x = startx;
760                            currMV->y = starty;
761                    }
762            return iMinSAD;
763    }
764    
765    
766    int32_t Full16_MainSearch(
767                                            const uint8_t * const pRef,
768                                            const uint8_t * const pRefH,
769                                            const uint8_t * const pRefV,
770                                            const uint8_t * const pRefHV,
771                                            const uint8_t * const cur,
772                                            const int x, const int y,
773                                            int32_t startx, int32_t starty,
774                                            int32_t iMinSAD,
775                                            VECTOR * const currMV,
776                                            const VECTOR * const pmv,
777                                            const int32_t min_dx, const int32_t max_dx,
778                                            const int32_t min_dy, const int32_t max_dy,
779                                            const int32_t iEdgedWidth,
780                                            const int32_t iDiamondSize,
781                                            const int32_t iFcode,
782                                            const int32_t iQuant,
783                                            int iFound)
784    {
785            int32_t iSAD;
786            int32_t dx,dy;
787            VECTOR backupMV;
788            backupMV.x = startx;
789            backupMV.y = starty;
790    
791            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
792                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
793                            NOCHECK_MV16_CANDIDATE(dx,dy);
794    
795            return iMinSAD;
796    }
797    
798    int32_t Full8_MainSearch(
799                                            const uint8_t * const pRef,
800                                            const uint8_t * const pRefH,
801                                            const uint8_t * const pRefV,
802                                            const uint8_t * const pRefHV,
803                                            const uint8_t * const cur,
804                                            const int x, const int y,
805                                            int32_t startx, int32_t starty,
806                                            int32_t iMinSAD,
807                                            VECTOR * const currMV,
808                                            const VECTOR * const pmv,
809                                            const int32_t min_dx, const int32_t max_dx,
810                                            const int32_t min_dy, const int32_t max_dy,
811                                            const int32_t iEdgedWidth,
812                                            const int32_t iDiamondSize,
813                                            const int32_t iFcode,
814                                            const int32_t iQuant,
815                                            int iFound)
816    {
817            int32_t iSAD;
818            int32_t dx,dy;
819            VECTOR backupMV;
820            backupMV.x = startx;
821            backupMV.y = starty;
822    
823            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
824                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
825                            NOCHECK_MV8_CANDIDATE(dx,dy);
826    
827            return iMinSAD;
828    }
829    
830    
831    
832    int32_t Halfpel16_Refine(
833                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
834                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
835                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 585  Line 864 
864    
865  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
866    
867    
868  int32_t PMVfastSearch16(  int32_t PMVfastSearch16(
869                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
870                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
# Line 593  Line 873 
873                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
874                                          const int x, const int y,                                          const int x, const int y,
875                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
876                                          MBParam * const pParam,                                          const uint32_t iQuant,
877                                          MACROBLOCK * const pMBs,                                          const uint32_t iFcode,
878                                            const MBParam * const pParam,
879                                            const MACROBLOCK * const pMBs,
880                                            const MACROBLOCK * const prevMBs,
881                                          VECTOR * const currMV,                                          VECTOR * const currMV,
882                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
883  {  {
884          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;  
885          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
886          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
887          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 622  Line 903 
903          VECTOR pmv[4];          VECTOR pmv[4];
904          int32_t psad[4];          int32_t psad[4];
905    
906          MACROBLOCK * const pMB = pMBs + x + y * iWcount;          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
907            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
908    
909          static int32_t threshA,threshB;          static int32_t threshA,threshB;
910          int32_t bPredEq;          int32_t bPredEq;
# Line 666  Line 948 
948          If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2          If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
949  */  */
950    
951          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )          if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) )
952                  iFound=2;                  iFound=2;
953    
954  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
# Line 718  Line 1000 
1000          iMinSAD = sad16( cur,          iMinSAD = sad16( cur,
1001                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1002                  iEdgedWidth, MV_MAX_ERROR);                  iEdgedWidth, MV_MAX_ERROR);
1003          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1004    
1005          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1006                  {                  {
1007    
1008                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1009                                  goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1010                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
1011                                  goto step10;                          goto PMVfast16_Terminate_with_Refine;
1012                  }                  }
1013    
1014  /*  /*
1015  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.
1016          Also calculate (0,0) but do not subtract offset.          Also calculate (0,0) but do not subtract offset.
1017          Let MinSAD be the smallest SAD up to this point.          Let MinSAD be the smallest SAD up to this point.
1018          If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1019  */  */
1020    
1021  // (0,0) is always possible  // (0,0) is always possible
# Line 741  Line 1023 
1023          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1024    
1025  // previous frame MV is always possible  // previous frame MV is always possible
1026          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1027    
1028  // left neighbour, if allowed  // left neighbour, if allowed
1029          if (x != 0)          if (x != 0)
# Line 763  Line 1045 
1045                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1046    
1047  // top right neighbour, if allowed  // top right neighbour, if allowed
1048                  if (x != (iWcount-1))                  if ((uint32_t)x != (iWcount-1))
1049                  {                  {
1050                          if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!(MotionFlags & PMV_HALFPEL16 ))
1051                          {       pmv[3].x = EVEN(pmv[3].x);                          {       pmv[3].x = EVEN(pmv[3].x);
# Line 773  Line 1055 
1055                  }                  }
1056          }          }
1057    
1058            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )
1059                    iMinSAD -= MV16_00_BIAS;
1060    
1061    
1062  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1063     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.
1064  */  */
1065    
1066          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1067                  {                  {
1068                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1069                                  goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1070                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
1071                                  goto step10;                          goto PMVfast16_Terminate_with_Refine;
1072                  }                  }
1073    
1074    
# Line 799  Line 1085 
1085          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1086    
1087  /* 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 */
1088          iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1089                  x, y,                  x, y,
1090                  currMV->x, currMV->y, iMinSAD, &newMV,                  currMV->x, currMV->y, iMinSAD, &newMV,
1091                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 815  Line 1101 
1101  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1102    
1103                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1104                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1105                                  x, y,                                  x, y,
1106                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1107                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 828  Line 1114 
1114                  }                  }
1115    
1116                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1117                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1118                                  x, y,                                  x, y,
1119                          0, 0, iMinSAD, &newMV,                          0, 0, iMinSAD, &newMV,
1120                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 845  Line 1131 
1131          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.
1132  */  */
1133    
1134  step10:  PMVfast16_Terminate_with_Refine:
1135          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1136                  iMinSAD = PMVfastSearch16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1137                                  x, y,                                  x, y,
1138                                  currMV, iMinSAD,                                  currMV, iMinSAD,
1139                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1140    
1141  step10b:  PMVfast16_Terminate_without_Refine:
1142          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1143          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1144          return iMinSAD;          return iMinSAD;
# Line 863  Line 1149 
1149    
1150    
1151    
1152  int32_t PMVfastSearch8_MainSearch(  int32_t Diamond8_MainSearch(
1153                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
1154                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1155                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 920  Line 1206 
1206          return iMinSAD;          return iMinSAD;
1207  }  }
1208    
1209  int32_t PMVfastSearch8_Refine(  int32_t Halfpel8_Refine(
1210                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
1211                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1212                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 963  Line 1249 
1249                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1250                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1251                                          const int x, const int y,                                          const int x, const int y,
1252                                          const int start_x, int start_y,                                          const int start_x, const int start_y,
1253                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1254                                          MBParam * const pParam,                                          const uint32_t iQuant,
1255                                          MACROBLOCK * const pMBs,                                          const uint32_t iFcode,
1256                                            const MBParam * const pParam,
1257                                            const MACROBLOCK * const pMBs,
1258                                            const MACROBLOCK * const prevMBs,
1259                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1260                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1261  {  {
1262          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;  
1263          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1264          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1265          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 992  Line 1278 
1278          VECTOR newMV;          VECTOR newMV;
1279          VECTOR backupMV;          VECTOR backupMV;
1280    
1281          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1282            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1283    
1284          static int32_t threshA,threshB;          static int32_t threshA,threshB;
1285          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
# Line 1004  Line 1291 
1291      get_range(&min_dx, &max_dx, &min_dy, &max_dy,      get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1292                          x, y, 8, iWidth, iHeight, iFcode);                          x, y, 8, iWidth, iHeight, iFcode);
1293    
 /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */  
   
1294          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))
1295          { min_dx = EVEN(min_dx);          { min_dx = EVEN(min_dx);
1296            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
# Line 1038  Line 1323 
1323          If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2          If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1324  */  */
1325    
1326          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )          if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) )
1327                  iFound=2;                  iFound=2;
1328    
1329  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
# Line 1069  Line 1354 
1354          iMinSAD = sad8( cur,          iMinSAD = sad8( cur,
1355                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1356                  iEdgedWidth);                  iEdgedWidth);
1357          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode, iQuant);
1358    
1359          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock])) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1360                  {                  {
1361                          if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1362                                  goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1363                          if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1364                                  goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1365                  }                  }
1366    
1367    
1368  /*  /*
1369  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.
1370          Also calculate (0,0) but do not subtract offset.          Also calculate (0,0) but do not subtract offset.
1371          Let MinSAD be the smallest SAD up to this point.          Let MinSAD be the smallest SAD up to this point.
1372          If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1373  */  */
1374    
1375  // the prediction might be even better than mv16  // the prediction might be even better than mv16
# Line 1093  Line 1379 
1379          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1380    
1381  // previous frame MV is always possible  // previous frame MV is always possible
1382          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1383    
1384  // left neighbour, if allowed  // left neighbour, if allowed
1385          if (psad[1] != MV_MAX_ERROR)          if (psad[1] != MV_MAX_ERROR)
# Line 1125  Line 1411 
1411                  }                  }
1412          }          }
1413    
1414            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1415                    iMinSAD -= MV8_00_BIAS;
1416    
1417    
1418  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1419     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.
1420  */  */
1421    
1422          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1423                  {                  {
1424                          if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1425                                  goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1426                          if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1427                                  goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1428                  }                  }
1429    
1430  /************ (Diamond Search)  **************/  /************ (Diamond Search)  **************/
# Line 1150  Line 1440 
1440          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1441    
1442  /* 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 */
1443          iSAD = PMVfastSearch8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1444                  x, y,                  x, y,
1445                  currMV->x, currMV->y, iMinSAD, &newMV,                  currMV->x, currMV->y, iMinSAD, &newMV,
1446                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1166  Line 1456 
1456  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1457    
1458                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1459                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1460                                  x, y,                                  x, y,
1461                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1462                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1179  Line 1469 
1469                  }                  }
1470    
1471                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1472                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1473                                  x, y,                                  x, y,
1474                          0, 0, iMinSAD, &newMV,                          0, 0, iMinSAD, &newMV,
1475                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1196  Line 1486 
1486           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.
1487  */  */
1488    
1489  step10_8:  PMVfast8_Terminate_with_Refine:
1490          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1491                  iMinSAD = PMVfastSearch8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1492                                                     x, y,
1493                                                     currMV, iMinSAD,
1494                                                     pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1495    
1496    
1497    PMVfast8_Terminate_without_Refine:
1498            currPMV->x = currMV->x - pmv[0].x;
1499            currPMV->y = currMV->y - pmv[0].y;
1500    
1501            return iMinSAD;
1502    }
1503    
1504    int32_t EPZSSearch16(
1505                                            const uint8_t * const pRef,
1506                                            const uint8_t * const pRefH,
1507                                            const uint8_t * const pRefV,
1508                                            const uint8_t * const pRefHV,
1509                                            const IMAGE * const pCur,
1510                                            const int x, const int y,
1511                                            const uint32_t MotionFlags,
1512                                            const uint32_t iQuant,
1513                                            const uint32_t iFcode,
1514                                            const MBParam * const pParam,
1515                                            const MACROBLOCK * const pMBs,
1516                                            const MACROBLOCK * const prevMBs,
1517                                            VECTOR * const currMV,
1518                                            VECTOR * const currPMV)
1519    {
1520        const uint32_t iWcount = pParam->mb_width;
1521        const uint32_t iHcount = pParam->mb_height;
1522    
1523            const int32_t iWidth = pParam->width;
1524            const int32_t iHeight = pParam->height;
1525            const int32_t iEdgedWidth = pParam->edged_width;
1526    
1527            const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
1528    
1529            int32_t min_dx;
1530            int32_t max_dx;
1531            int32_t min_dy;
1532            int32_t max_dy;
1533    
1534            VECTOR newMV;
1535            VECTOR backupMV;
1536    
1537            VECTOR pmv[4];
1538            int32_t psad[8];
1539    
1540            static MACROBLOCK * oldMBs = NULL;
1541            const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1542            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1543            MACROBLOCK * oldMB = NULL;
1544    
1545            static int32_t thresh2;
1546            int32_t bPredEq;
1547            int32_t iMinSAD,iSAD=9999;
1548    
1549            MainSearch16FuncPtr EPZSMainSearchPtr;
1550    
1551            if (oldMBs == NULL)
1552            {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));
1553    //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1554            }
1555            oldMB = oldMBs + x + y * iWcount;
1556    
1557    /* Get maximum range */
1558            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1559                            x, y, 16, iWidth, iHeight, iFcode);
1560    
1561            if (!(MotionFlags & PMV_HALFPEL16 ))
1562            { min_dx = EVEN(min_dx);
1563              max_dx = EVEN(max_dx);
1564              min_dy = EVEN(min_dy);
1565              max_dy = EVEN(max_dy);
1566            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1567    
1568            bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1569    
1570    /* Step 4: Calculate SAD around the Median prediction.
1571            MinSAD=SAD
1572            If Motion Vector equal to Previous frame motion vector
1573                    and MinSAD<PrevFrmSAD goto Step 10.
1574            If SAD<=256 goto Step 10.
1575    */
1576    
1577    // Prepare for main loop
1578    
1579            *currMV=pmv[0];         /* current best := median prediction */
1580            if (!(MotionFlags & PMV_HALFPEL16))
1581            {
1582                    currMV->x = EVEN(currMV->x);
1583                    currMV->y = EVEN(currMV->y);
1584            }
1585    
1586            if (currMV->x > max_dx)
1587                    currMV->x=max_dx;
1588            if (currMV->x < min_dx)
1589                    currMV->x=min_dx;
1590            if (currMV->y > max_dy)
1591                    currMV->y=max_dy;
1592            if (currMV->y < min_dy)
1593                    currMV->y=min_dy;
1594    
1595    /***************** This is predictor SET A: only median prediction ******************/
1596    
1597            iMinSAD = sad16( cur,
1598                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1599                    iEdgedWidth, MV_MAX_ERROR);
1600            iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1601    
1602    // thresh1 is fixed to 256
1603            if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1604                    {
1605                            if (MotionFlags & PMV_QUICKSTOP16)
1606                                    goto EPZS16_Terminate_without_Refine;
1607                            if (MotionFlags & PMV_EARLYSTOP16)
1608                                    goto EPZS16_Terminate_with_Refine;
1609                    }
1610    
1611    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1612    
1613    // previous frame MV
1614            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1615    
1616    // set threshhold based on Min of Prediction and SAD of collocated block
1617    // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
1618    
1619            if ((x==0) && (y==0) )
1620            {
1621                    thresh2 =  512;
1622            }
1623            else
1624            {
1625    /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
1626    
1627                    thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
1628            }
1629    
1630    // MV=(0,0) is often a good choice
1631    
1632            CHECK_MV16_ZERO;
1633    
1634    
1635    // left neighbour, if allowed
1636            if (x != 0)
1637            {
1638                    if (!(MotionFlags & PMV_HALFPEL16 ))
1639                    {       pmv[1].x = EVEN(pmv[1].x);
1640                            pmv[1].y = EVEN(pmv[1].y);
1641                    }
1642                    CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1643            }
1644    
1645    // top neighbour, if allowed
1646            if (y != 0)
1647            {
1648                    if (!(MotionFlags & PMV_HALFPEL16 ))
1649                    {       pmv[2].x = EVEN(pmv[2].x);
1650                            pmv[2].y = EVEN(pmv[2].y);
1651                    }
1652                    CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1653    
1654    // top right neighbour, if allowed
1655                    if ((uint32_t)x != (iWcount-1))
1656                    {
1657                            if (!(MotionFlags & PMV_HALFPEL16 ))
1658                            {       pmv[3].x = EVEN(pmv[3].x);
1659                                    pmv[3].y = EVEN(pmv[3].y);
1660                            }
1661                            CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
1662                    }
1663            }
1664    
1665    /* Terminate if MinSAD <= T_2
1666       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1667    */
1668    
1669            if ( (iMinSAD <= thresh2)
1670                    || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )
1671                    {
1672                            if (MotionFlags & PMV_QUICKSTOP16)
1673                                    goto EPZS16_Terminate_without_Refine;
1674                            if (MotionFlags & PMV_EARLYSTOP16)
1675                                    goto EPZS16_Terminate_with_Refine;
1676                    }
1677    
1678    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1679    
1680            backupMV = prevMB->mvs[0];              // collocated MV
1681            backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x );    // acceleration X
1682            backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y );    // acceleration Y
1683    
1684            CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
1685    
1686    // left neighbour
1687            if (x != 0)
1688                    CHECK_MV16_CANDIDATE((prevMB-1)->mvs[0].x,(prevMB-1)->mvs[0].y);
1689    
1690    // top neighbour
1691            if (y != 0)
1692                    CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);
1693    
1694    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
1695    
1696            if ((uint32_t)x != iWcount-1)
1697                    CHECK_MV16_CANDIDATE((prevMB+1)->mvs[0].x,(prevMB+1)->mvs[0].y);
1698    
1699    // bottom neighbour, dito
1700            if ((uint32_t)y != iHcount-1)
1701                    CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);
1702    
1703    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
1704            if (iMinSAD <= thresh2)
1705                    {
1706                            if (MotionFlags & PMV_QUICKSTOP16)
1707                                    goto EPZS16_Terminate_without_Refine;
1708                            if (MotionFlags & PMV_EARLYSTOP16)
1709                                    goto EPZS16_Terminate_with_Refine;
1710                    }
1711    
1712    /************ (if Diamond Search)  **************/
1713    
1714            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1715    
1716    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1717    
1718            if (MotionFlags & PMV_USESQUARES16)
1719                    EPZSMainSearchPtr = Square16_MainSearch;
1720            else
1721                    EPZSMainSearchPtr = Diamond16_MainSearch;
1722    
1723            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1724                            x, y,
1725                            currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1726                            2, iFcode, iQuant, 0);
1727    
1728            if (iSAD < iMinSAD)
1729            {
1730                    *currMV = newMV;
1731                    iMinSAD = iSAD;
1732            }
1733    
1734    
1735            if (MotionFlags & PMV_EXTSEARCH16)
1736            {
1737    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1738    
1739                    if (!(MVequal(pmv[0],backupMV)) )
1740                    {
1741                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1742                                    x, y,
1743                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1744                                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1745                    }
1746    
1747                    if (iSAD < iMinSAD)
1748                    {
1749                            *currMV = newMV;
1750                            iMinSAD = iSAD;
1751                    }
1752    
1753                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1754                    {
1755                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1756                                    x, y,
1757                            0, 0, iMinSAD, &newMV,
1758                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1759    
1760                            if (iSAD < iMinSAD)
1761                            {
1762                                    *currMV = newMV;
1763                                    iMinSAD = iSAD;
1764                            }
1765                    }
1766            }
1767    
1768    /***************        Choose best MV found     **************/
1769    
1770    EPZS16_Terminate_with_Refine:
1771            if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1772                    iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1773                                  x, y,                                  x, y,
1774                                  currMV, iMinSAD,                                  currMV, iMinSAD,
1775                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1776    
1777  step10_8b:  EPZS16_Terminate_without_Refine:
1778    
1779            *oldMB = *prevMB;
1780    
1781          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1782          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1783            return iMinSAD;
1784    }
1785    
1786    
1787    int32_t EPZSSearch8(
1788                                            const uint8_t * const pRef,
1789                                            const uint8_t * const pRefH,
1790                                            const uint8_t * const pRefV,
1791                                            const uint8_t * const pRefHV,
1792                                            const IMAGE * const pCur,
1793                                            const int x, const int y,
1794                                            const int start_x, const int start_y,
1795                                            const uint32_t MotionFlags,
1796                                            const uint32_t iQuant,
1797                                            const uint32_t iFcode,
1798                                            const MBParam * const pParam,
1799                                            const MACROBLOCK * const pMBs,
1800                                            const MACROBLOCK * const prevMBs,
1801                                            VECTOR * const currMV,
1802                                            VECTOR * const currPMV)
1803    {
1804    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
1805    
1806            const uint32_t iWcount = pParam->mb_width;
1807            const int32_t iWidth = pParam->width;
1808            const int32_t iHeight = pParam->height;
1809            const int32_t iEdgedWidth = pParam->edged_width;
1810    
1811            const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
1812    
1813            int32_t iDiamondSize=1;
1814    
1815            int32_t min_dx;
1816            int32_t max_dx;
1817            int32_t min_dy;
1818            int32_t max_dy;
1819    
1820            VECTOR newMV;
1821            VECTOR backupMV;
1822    
1823            VECTOR pmv[4];
1824            int32_t psad[8];
1825    
1826            const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
1827    
1828            const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1829            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1830    
1831            int32_t bPredEq;
1832            int32_t iMinSAD,iSAD=9999;
1833    
1834            MainSearch8FuncPtr EPZSMainSearchPtr;
1835    
1836    /* Get maximum range */
1837            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1838                            x, y, 8, iWidth, iHeight, iFcode);
1839    
1840    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1841    
1842            if (!(MotionFlags & PMV_HALFPEL8 ))
1843            { min_dx = EVEN(min_dx);
1844              max_dx = EVEN(max_dx);
1845              min_dy = EVEN(min_dy);
1846              max_dy = EVEN(max_dy);
1847            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1848    
1849            bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);
1850    
1851    
1852    /* Step 4: Calculate SAD around the Median prediction.
1853            MinSAD=SAD
1854            If Motion Vector equal to Previous frame motion vector
1855                    and MinSAD<PrevFrmSAD goto Step 10.
1856            If SAD<=256 goto Step 10.
1857    */
1858    
1859    // Prepare for main loop
1860    
1861    
1862            if (!(MotionFlags & PMV_HALFPEL8))
1863            {
1864                    currMV->x = EVEN(currMV->x);
1865                    currMV->y = EVEN(currMV->y);
1866            }
1867    
1868            if (currMV->x > max_dx)
1869                    currMV->x=max_dx;
1870            if (currMV->x < min_dx)
1871                    currMV->x=min_dx;
1872            if (currMV->y > max_dy)
1873                    currMV->y=max_dy;
1874            if (currMV->y < min_dy)
1875                    currMV->y=min_dy;
1876    
1877    /***************** This is predictor SET A: only median prediction ******************/
1878    
1879    
1880            iMinSAD = sad8( cur,
1881                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1882                    iEdgedWidth);
1883            iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1884    
1885    
1886    // thresh1 is fixed to 256
1887            if (iMinSAD < 256/4 )
1888                    {
1889                            if (MotionFlags & PMV_QUICKSTOP8)
1890                                    goto EPZS8_Terminate_without_Refine;
1891                            if (MotionFlags & PMV_EARLYSTOP8)
1892                                    goto EPZS8_Terminate_with_Refine;
1893                    }
1894    
1895    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1896    
1897    
1898    // MV=(0,0) is often a good choice
1899            CHECK_MV8_ZERO;
1900    
1901    // previous frame MV
1902            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1903    
1904    // left neighbour, if allowed
1905            if (psad[1] != MV_MAX_ERROR)
1906            {
1907                    if (!(MotionFlags & PMV_HALFPEL8 ))
1908                    {       pmv[1].x = EVEN(pmv[1].x);
1909                            pmv[1].y = EVEN(pmv[1].y);
1910                    }
1911                    CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1912            }
1913    
1914    // top neighbour, if allowed
1915            if (psad[2] != MV_MAX_ERROR)
1916            {
1917                    if (!(MotionFlags & PMV_HALFPEL8 ))
1918                    {       pmv[2].x = EVEN(pmv[2].x);
1919                            pmv[2].y = EVEN(pmv[2].y);
1920                    }
1921                    CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1922    
1923    // top right neighbour, if allowed
1924                    if (psad[3] != MV_MAX_ERROR)
1925                    {
1926                            if (!(MotionFlags & PMV_HALFPEL8 ))
1927                            {       pmv[3].x = EVEN(pmv[3].x);
1928                                    pmv[3].y = EVEN(pmv[3].y);
1929                            }
1930                            CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
1931                    }
1932            }
1933    
1934    /*  // this bias is zero anyway, at the moment!
1935    
1936            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
1937                    iMinSAD -= MV8_00_BIAS;
1938    
1939    */
1940    
1941    /* Terminate if MinSAD <= T_2
1942       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1943    */
1944    
1945            if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */
1946                    {
1947                            if (MotionFlags & PMV_QUICKSTOP8)
1948                                    goto EPZS8_Terminate_without_Refine;
1949                            if (MotionFlags & PMV_EARLYSTOP8)
1950                                    goto EPZS8_Terminate_with_Refine;
1951                    }
1952    
1953    /************ (Diamond Search)  **************/
1954    
1955            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1956    
1957            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1958                    iDiamondSize *= 2;
1959    
1960    /* default: use best prediction as starting point for one call of EPZS_MainSearch */
1961    
1962    /* // there is no EPZS^2 for inter4v at the moment
1963    
1964            if (MotionFlags & PMV_USESQUARES8)
1965                    EPZSMainSearchPtr = Square8_MainSearch;
1966            else
1967    */
1968    
1969            EPZSMainSearchPtr = Diamond8_MainSearch;
1970    
1971            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1972                    x, y,
1973                    currMV->x, currMV->y, iMinSAD, &newMV,
1974                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1975                    iDiamondSize, iFcode, iQuant, 0);
1976    
1977    
1978            if (iSAD < iMinSAD)
1979            {
1980                    *currMV = newMV;
1981                    iMinSAD = iSAD;
1982            }
1983    
1984            if (MotionFlags & PMV_EXTSEARCH8)
1985            {
1986    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1987    
1988                    if (!(MVequal(pmv[0],backupMV)) )
1989                    {
1990                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1991                                    x, y,
1992                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1993                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
1994    
1995                            if (iSAD < iMinSAD)
1996                            {
1997                                    *currMV = newMV;
1998                                    iMinSAD = iSAD;
1999                            }
2000                    }
2001    
2002                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
2003                    {
2004                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2005                                    x, y,
2006                            0, 0, iMinSAD, &newMV,
2007                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
2008    
2009                            if (iSAD < iMinSAD)
2010                            {
2011                                    *currMV = newMV;
2012                                    iMinSAD = iSAD;
2013                            }
2014                    }
2015            }
2016    
2017    /***************        Choose best MV found     **************/
2018    
2019    EPZS8_Terminate_with_Refine:
2020            if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2021                    iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
2022                                    x, y,
2023                                    currMV, iMinSAD,
2024                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
2025    
2026    EPZS8_Terminate_without_Refine:
2027    
2028            currPMV->x = currMV->x - pmv[0].x;
2029            currPMV->y = currMV->y - pmv[0].y;
2030          return iMinSAD;          return iMinSAD;
2031  }  }
2032    
2033    
2034    
2035    
2036    
2037    /* ***********************************************************
2038            bvop motion estimation
2039    // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
2040    ***************************************************************/
2041    
2042    
2043    void MotionEstimationBVOP(
2044                            MBParam * const pParam,
2045                            FRAMEINFO * const frame,
2046    
2047                            // forward (past) reference
2048                            const MACROBLOCK * const f_mbs,
2049                        const IMAGE * const f_ref,
2050                            const IMAGE * const f_refH,
2051                        const IMAGE * const f_refV,
2052                            const IMAGE * const f_refHV,
2053                            // backward (future) reference
2054                            const MACROBLOCK * const b_mbs,
2055                        const IMAGE * const b_ref,
2056                            const IMAGE * const b_refH,
2057                        const IMAGE * const b_refV,
2058                            const IMAGE * const b_refHV)
2059    {
2060        const uint32_t mb_width = pParam->mb_width;
2061        const uint32_t mb_height = pParam->mb_height;
2062            const int32_t edged_width = pParam->edged_width;
2063    
2064            uint32_t i,j;
2065    
2066            int32_t f_sad16;
2067            int32_t b_sad16;
2068            int32_t i_sad16;
2069            int32_t d_sad16;
2070            int32_t best_sad;
2071    
2072            VECTOR pmv_dontcare;
2073    
2074            // note: i==horizontal, j==vertical
2075        for (j = 0; j < mb_height; j++)
2076            {
2077                    for (i = 0; i < mb_width; i++)
2078                    {
2079                            MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
2080                            const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
2081                            const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
2082    
2083                            if (b_mb->mode == MODE_INTER
2084                                    && b_mb->cbp == 0
2085                                    && b_mb->mvs[0].x == 0
2086                                    && b_mb->mvs[0].y == 0)
2087                            {
2088                                    mb->mode = MODE_NOT_CODED;
2089                                    mb->mvs[0].x = 0;
2090                                    mb->mvs[0].y = 0;
2091                                    mb->b_mvs[0].x = 0;
2092                                    mb->b_mvs[0].y = 0;
2093                                    continue;
2094                            }
2095    
2096    
2097                            // forward search
2098                            f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2099                                                    &frame->image,
2100                                                    i, j,
2101                                                    frame->motion_flags,  frame->quant, frame->fcode,
2102                                                    pParam,
2103                                                    f_mbs, f_mbs /* todo */,
2104                                                    &mb->mvs[0], &pmv_dontcare);    // ignore pmv
2105    
2106                            // backward search
2107                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2108                                                    &frame->image,
2109                                                    i, j,
2110                                                    frame->motion_flags,  frame->quant, frame->bcode,
2111                                                    pParam,
2112                                                    b_mbs, b_mbs, /* todo */
2113                                                    &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv
2114    
2115                            // interpolate search (simple, but effective)
2116                            i_sad16 = sad16bi_c(
2117                                            frame->image.y + i*16 + j*16*edged_width,
2118                                            get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2119                                                    i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),
2120                                            get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2121                                                    i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),
2122                                            edged_width);
2123    
2124                            // TODO: direct search
2125                            // predictor + range of [-32,32]
2126                            d_sad16 = 65535;
2127    
2128    
2129                            if (f_sad16 < b_sad16)
2130                            {
2131                                    best_sad = f_sad16;
2132                                    mb->mode = MODE_FORWARD;
2133                            }
2134                            else
2135                            {
2136                                    best_sad = b_sad16;
2137                                    mb->mode = MODE_BACKWARD;
2138                            }
2139    
2140                            if (i_sad16 < best_sad)
2141                            {
2142                                    best_sad = i_sad16;
2143                                    mb->mode = MODE_INTERPOLATE;
2144                            }
2145    
2146                            if (d_sad16 < best_sad)
2147                            {
2148                                    best_sad = d_sad16;
2149                                    mb->mode = MODE_DIRECT;
2150                            }
2151    
2152                    }
2153            }
2154    }

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

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