[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 136, Thu Apr 25 06:55:00 2002 UTC
# Line 2  Line 2 
2   *   *
3   *  Modifications:   *  Modifications:
4   *   *
5     *      25.04.2002 partial prevMB conversion
6     *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>
7     *  14.04.2002 added MotionEstimationBVOP()
8     *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between
9     *             EPZS and EPZS^2
10   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop
11   *             PMVFast_Refine to support multiple searches with different start points   *             PMVFast_Refine to support multiple searches with different start points
12   *      07.01.2002 uv-block-based interpolation   *      07.01.2002 uv-block-based interpolation
# Line 31  Line 36 
36    
37  #include <assert.h>  #include <assert.h>
38  #include <stdio.h>  #include <stdio.h>
39    #include <stdlib.h>
40    
41  #include "../encoder.h"  #include "../encoder.h"
42  #include "../utils/mbfunctions.h"  #include "../utils/mbfunctions.h"
43  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
44  #include "../global.h"  #include "../global.h"
45  #include "../utils/timer.h"  #include "../utils/timer.h"
46    #include "motion.h"
47  #include "sad.h"  #include "sad.h"
48    
49  // very large value  // very large value
# Line 65  Line 72 
72  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)
73    
74    
75  #define MIN(X, Y) ((X)<(Y)?(X):(Y))  int32_t PMVfastSearch16(
 #define MAX(X, Y) ((X)>(Y)?(X):(Y))  
 #define ABS(X) (((X)>0)?(X):-(X))  
 #define SIGN(X) (((X)>0)?1:-1)  
   
   
 int32_t PMVfastSearch8(  
76                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
77                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
78                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
79                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
80                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
81                                          const int x, const int y,                                          const int x, const int y,
82                                          const int start_x, int start_y,                                          const uint32_t MotionFlags,
83                                          const uint32_t iQuality,                                          const uint32_t iQuant,
84                                          MBParam * const pParam,                                          const uint32_t iFcode,
85                                          MACROBLOCK * const pMBs,                                          const MBParam * const pParam,
86                                            const MACROBLOCK * const pMBs,
87                                            const MACROBLOCK * const prevMBs,
88                                          VECTOR * const currMV,                                          VECTOR * const currMV,
89                                          VECTOR * const currPMV);                                          VECTOR * const currPMV);
90    
91  int32_t PMVfastSearch16(  int32_t EPZSSearch16(
92                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
93                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
94                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
95                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
96                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
97                                          const int x, const int y,                                          const int x, const int y,
98                                          const uint32_t iQuality,                                          const uint32_t MotionFlags,
99                                          MBParam * const pParam,                                          const uint32_t iQuant,
100                                          MACROBLOCK * const pMBs,                                          const uint32_t iFcode,
101                                            const MBParam * const pParam,
102                                            const MACROBLOCK * const pMBs,
103                                            const MACROBLOCK * const prevMBs,
104                                          VECTOR * const currMV,                                          VECTOR * const currMV,
105                                          VECTOR * const currPMV);                                          VECTOR * const currPMV);
106    
107    
108    int32_t PMVfastSearch8(
109                                            const uint8_t * const pRef,
110                                            const uint8_t * const pRefH,
111                                            const uint8_t * const pRefV,
112                                            const uint8_t * const pRefHV,
113                                            const IMAGE * const pCur,
114                                            const int x, const int y,
115                                            const int start_x, const int start_y,
116                                            const uint32_t MotionFlags,
117                                            const uint32_t iQuant,
118                                            const uint32_t iFcode,
119                                            const MBParam * const pParam,
120                                            const MACROBLOCK * const pMBs,
121                                            const MACROBLOCK * const prevMBs,
122                                            VECTOR * const currMV,
123                                            VECTOR * const currPMV);
124    
125  /* diamond search stuff  int32_t EPZSSearch8(
126     keep the the sequence in circular order (so optimization works)                                          const uint8_t * const pRef,
127  */                                          const uint8_t * const pRefH,
128                                            const uint8_t * const pRefV,
129                                            const uint8_t * const pRefHV,
130                                            const IMAGE * const pCur,
131                                            const int x, const int y,
132                                            const int start_x, const int start_y,
133                                            const uint32_t MotionFlags,
134                                            const uint32_t iQuant,
135                                            const uint32_t iFcode,
136                                            const MBParam * const pParam,
137                                            const MACROBLOCK * const pMBs,
138                                            const MACROBLOCK * const prevMBs,
139                                            VECTOR * const currMV,
140                                            VECTOR * const currPMV);
141    
 typedef struct  
 {  
         int32_t dx;  
         int32_t dy;  
 }  
 DPOINT;  
142    
143    typedef int32_t (MainSearch16Func)(
144            const uint8_t * const pRef,
145            const uint8_t * const pRefH,
146            const uint8_t * const pRefV,
147            const uint8_t * const pRefHV,
148            const uint8_t * const cur,
149            const int x, const int y,
150            int32_t startx, int32_t starty,
151            int32_t iMinSAD,
152            VECTOR * const currMV,
153            const VECTOR * const pmv,
154            const int32_t min_dx, const int32_t max_dx,
155            const int32_t min_dy, const int32_t max_dy,
156            const int32_t iEdgedWidth,
157            const int32_t iDiamondSize,
158            const int32_t iFcode,
159            const int32_t iQuant,
160            int iFound);
161    
162  static const DPOINT diamond_small[4] =  typedef MainSearch16Func* MainSearch16FuncPtr;
 {  
         {0, 1}, {1, 0}, {0, -1}, {-1, 0}  
 };  
163    
164    
165  static const DPOINT diamond_large[8] =  typedef int32_t (MainSearch8Func)(
166  {          const uint8_t * const pRef,
167          {0, 2}, {1, 1}, {2, 0}, {1, -1}, {0, -2}, {-1, -1}, {-2, 0}, {-1, 1}          const uint8_t * const pRefH,
168  };          const uint8_t * const pRefV,
169            const uint8_t * const pRefHV,
170            const uint8_t * const cur,
171            const int x, const int y,
172            int32_t startx, int32_t starty,
173            int32_t iMinSAD,
174            VECTOR * const currMV,
175            const VECTOR * const pmv,
176            const int32_t min_dx, const int32_t max_dx,
177            const int32_t min_dy, const int32_t max_dy,
178            const int32_t iEdgedWidth,
179            const int32_t iDiamondSize,
180            const int32_t iFcode,
181            const int32_t iQuant,
182            int iFound);
183    
184    typedef MainSearch8Func* MainSearch8FuncPtr;
185    
186  // mv.length table  // mv.length table
187  static const uint32_t mvtab[33] = {  static const uint32_t mvtab[33] = {
# Line 173  Line 232 
232    
233    
234    
 /* 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)  
 {  
         const int search_range = 32 << (fcode - 1);  
     const int high = search_range - 1;  
     const int low = -search_range;  
   
         // convert full-pixel measurements to half pixel  
         const int hp_width = 2 * width;  
         const int hp_height = 2 * height;  
         const int hp_edge = 2 * block_sz;  
         const int hp_x = 2 * (x) * block_sz;            // we need _right end_ of block, not x-coordinate  
         const int hp_y = 2 * (y) * block_sz;            // same for _bottom end_  
   
     *max_dx = MIN(high, hp_width - hp_x);  
     *max_dy = MIN(high, hp_height - hp_y);  
     *min_dx = MAX(low,  -(hp_edge + hp_x));  
     *min_dy = MAX(low,  -(hp_edge + hp_y));  
 }  
   
   
 /* getref: calculate reference image pointer  
 the decision to use interpolation h/v/hv or the normal image is  
 based on dx & dy.  
 */  
   
 static __inline const uint8_t * get_ref(  
                                 const uint8_t * const refn,  
                                 const uint8_t * const refh,  
                                 const uint8_t * const refv,  
                                 const uint8_t * const refhv,  
                                 const uint32_t x, const uint32_t y,  
                                 const uint32_t block,                                   // block dimension, 8 or 16  
                                 const int32_t dx, const int32_t dy,  
                                 const uint32_t stride)  
 {  
         switch ( ((dx&1)<<1) + (dy&1) )         // ((dx%2)?2:0)+((dy%2)?1:0)  
     {  
         case 0 : return refn + (x*block+dx/2) + (y*block+dy/2)*stride;  
     case 1 : return refv + (x*block+dx/2) + (y*block+(dy-1)/2)*stride;  
         case 2 : return refh + (x*block+(dx-1)/2) + (y*block+dy/2)*stride;  
         default :  
         case 3 : return refhv + (x*block+(dx-1)/2) + (y*block+(dy-1)/2)*stride;  
         }  
 }  
   
   
 /* This is somehow a copy of get_ref, but with MV instead of X,Y */  
   
 static __inline const uint8_t * get_ref_mv(  
                                 const uint8_t * const refn,  
                                 const uint8_t * const refh,  
                                 const uint8_t * const refv,  
                                 const uint8_t * const refhv,  
                                 const uint32_t x, const uint32_t y,  
                                 const uint32_t block,                   // block dimension, 8 or 16  
                                 const VECTOR* mv,       // measured in half-pel!  
                                 const uint32_t stride)  
 {  
         switch ( (((mv->x)&1)<<1) + ((mv->y)&1) )  
     {  
         case 0 : return refn + (x*block+(mv->x)/2) + (y*block+(mv->y)/2)*stride;  
         case 1 : return refv + (x*block+(mv->x)/2) + (y*block+((mv->y)-1)/2)*stride;  
         case 2 : return refh + (x*block+((mv->x)-1)/2) + (y*block+(mv->y)/2)*stride;  
         default :  
         case 3 : return refhv + (x*block+((mv->x)-1)/2) + (y*block+((mv->y)-1)/2)*stride;  
         }  
 }  
235    
236  #ifndef SEARCH16  #ifndef SEARCH16
237  #define SEARCH16        PMVfastSearch16  #define SEARCH16        PMVfastSearch16
238    //#define SEARCH16      FullSearch16
239    //#define SEARCH16      EPZSSearch16
240  #endif  #endif
241    
242  #ifndef SEARCH8  #ifndef SEARCH8
243  #define SEARCH8         PMVfastSearch8  #define SEARCH8         PMVfastSearch8
244    //#define SEARCH8       EPZSSearch8
245  #endif  #endif
246    
247  bool MotionEstimation(  bool MotionEstimation(
                         MACROBLOCK * const pMBs,  
248                          MBParam * const pParam,                          MBParam * const pParam,
249                      const IMAGE * const pRef,          FRAMEINFO * const current,
250            FRAMEINFO * const reference,
251                          const IMAGE * const pRefH,                          const IMAGE * const pRefH,
252                      const IMAGE * const pRefV,                      const IMAGE * const pRefV,
253                          const IMAGE * const pRefHV,                          const IMAGE * const pRefHV,
                     IMAGE * const pCurrent,  
254                          const uint32_t iLimit)                          const uint32_t iLimit)
255    
256  {  {
257      const uint32_t iWcount = pParam->mb_width;      const uint32_t iWcount = pParam->mb_width;
258      const uint32_t iHcount = pParam->mb_height;      const uint32_t iHcount = pParam->mb_height;
259            MACROBLOCK * pMBs = current->mbs;
260            IMAGE * pCurrent = &current->image;
261    
262            MACROBLOCK * prevMBs = reference->mbs;  // previous frame
263            IMAGE * pRef = &reference->image;
264    
265    
266          uint32_t i, j, iIntra = 0;          uint32_t i, j, iIntra = 0;
267    
# Line 282  Line 272 
272      int32_t sad16;      int32_t sad16;
273      int32_t deviation;      int32_t deviation;
274    
275            if (sadInit)
276                    (*sadInit)();
277    
278    
279            /* eventhough we have a seperate prevMBs,
280               pmvfast/epsz does something "funny" with the previous frames data */
281    
282            for (i = 0; i < iHcount; i++)
283                    for (j = 0; j < iWcount; j++)
284                    {
285                            pMBs[j + i * iWcount].mvs[0] = prevMBs[j + i * iWcount].mvs[0];
286                            pMBs[j + i * iWcount].mvs[1] = prevMBs[j + i * iWcount].mvs[1];
287                            pMBs[j + i * iWcount].mvs[2] = prevMBs[j + i * iWcount].mvs[2];
288                            pMBs[j + i * iWcount].mvs[3] = prevMBs[j + i * iWcount].mvs[3];
289                    }
290    
291            /*dprintf("*** BEFORE ***");
292            for (i = 0; i < iHcount; i++)
293                    for (j = 0; j < iWcount; j++)
294                    {
295                            dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,
296                                    pMBs[j + i * iWcount].mode,
297                                    pMBs[j + i * iWcount].dquant,
298                                    pMBs[j + i * iWcount].mvs[0],
299                                    pMBs[j + i * iWcount].mvs[1],
300                                    pMBs[j + i * iWcount].mvs[2],
301                                    pMBs[j + i * iWcount].mvs[3],
302                                    prevMBs[j + i * iWcount].sad8[0],
303                                    prevMBs[j + i * iWcount].sad8[1],
304                                    prevMBs[j + i * iWcount].sad8[2],
305                                    prevMBs[j + i * iWcount].sad8[3],
306                                    prevMBs[j + i * iWcount].sad16);
307                    }
308            */
309    
310          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
311      for (i = 0; i < iHcount; i++)      for (i = 0; i < iHcount; i++)
312                  for (j = 0; j < iWcount; j++)                  for (j = 0; j < iWcount; j++)
313                  {                  {
314                          MACROBLOCK *pMB = &pMBs[j + i * iWcount];                          MACROBLOCK *pMB = &pMBs[j + i * iWcount];
315                            MACROBLOCK *prevMB = &prevMBs[j + i * iWcount];
316    
317                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
318                                            j, i, pParam->motion_flags,                                           j, i, current->motion_flags, current->quant, current->fcode,
319                                            pParam, pMBs, &mv16, &pmv16);                                           pParam, pMBs, prevMBs, &mv16, &pmv16);
320                          pMB->sad16=sad16;                          pMB->sad16=sad16;
321    
322    
# Line 306  Line 332 
332                          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;
333                          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;
334    
335                                    pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;
336    
337                          iIntra++;                          iIntra++;
338                          if(iIntra >= iLimit)                          if(iIntra >= iLimit)
339                                  return 1;                                  return 1;
# Line 313  Line 341 
341                          continue;                          continue;
342                  }                  }
343    
344                  if (pParam->global_flags & XVID_INTER4V)                          if (current->global_flags & XVID_INTER4V)
345                  {                  {
346                          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,
347                                          2 * j, 2 * i, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j, 2 * i, mv16.x, mv16.y,
348                                          pParam, pMBs, &pMB->mvs[0], &pMB->pmvs[0]);                                                             current->motion_flags, current->quant, current->fcode,
349                                                           pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);
350    
351                          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,
352                                          2 * j + 1, 2 * i, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j + 1, 2 * i, mv16.x, mv16.y,
353                                          pParam, pMBs, &pMB->mvs[1], &pMB->pmvs[1]);                                                             current->motion_flags, current->quant, current->fcode,
354                                                           pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);
355    
356                          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,
357                                          2 * j, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j, 2 * i + 1, mv16.x, mv16.y,
358                                          pParam, pMBs, &pMB->mvs[2], &pMB->pmvs[2]);                                                             current->motion_flags, current->quant, current->fcode,
359                                                           pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);
360    
361                          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,
362                                          2 * j + 1, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j + 1, 2 * i + 1, mv16.x, mv16.y,
363                                          pParam, pMBs, &pMB->mvs[3], &pMB->pmvs[3]);                                                             current->motion_flags, current->quant, current->fcode,
364                                                           pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);
365    
366                          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];
367                  }                  }
# Line 339  Line 371 
371                          mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                          mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v
372                  */                  */
373    
374                  if (pMB->dquant == NO_CHANGE) {                          if (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE)
375                          if (((pParam->global_flags & XVID_INTER4V)==0) ||                          {
376                                  (sad16 < (sad8 + (int32_t)(IMV16X16 * pParam->quant)))) {                                  if (((current->global_flags & XVID_INTER4V)==0) ||
377                                        (sad16 < (sad8 + (int32_t)(IMV16X16 * current->quant))))
378                                    {
379    
380                                  sad8 = sad16;                                  sad8 = sad16;
381                                  pMB->mode = MODE_INTER;                                  pMB->mode = MODE_INTER;
# Line 364  Line 398 
398                  }                  }
399          }          }
400    
401    /*      dprintf("*** AFTER ***", pMBs[0].b_mvs[0].x);
402            for (i = 0; i < iHcount; i++)
403                    for (j = 0; j < iWcount; j++)
404                    {
405                            dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,
406                                    pMBs[j + i * iWcount].mode,
407                                    pMBs[j + i * iWcount].dquant,
408                                    pMBs[j + i * iWcount].mvs[0],
409                                    pMBs[j + i * iWcount].mvs[1],
410                                    pMBs[j + i * iWcount].mvs[2],
411                                    pMBs[j + i * iWcount].mvs[3],
412                                    pMBs[j + i * iWcount].sad8[0],
413                                    pMBs[j + i * iWcount].sad8[1],
414                                    pMBs[j + i * iWcount].sad8[2],
415                                    pMBs[j + i * iWcount].sad8[3],
416                                    pMBs[j + i * iWcount].sad16);
417                    }
418            */
419    
420          return 0;          return 0;
421  }  }
422    
# Line 384  Line 437 
437      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
438  }  }
439    
440    #define NOCHECK_MV16_CANDIDATE(X,Y) { \
441        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
442        iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\
443        if (iSAD < iMinSAD) \
444        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
445    }
446    
447  #define CHECK_MV16_CANDIDATE(X,Y) { \  #define CHECK_MV16_CANDIDATE(X,Y) { \
448    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
# Line 423  Line 482 
482    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
483  }  }
484    
485    #define NOCHECK_MV8_CANDIDATE(X,Y) \
486      { \
487        iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
488        iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\
489        if (iSAD < iMinSAD) \
490        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
491    }
492    
493  #define CHECK_MV8_CANDIDATE(X,Y) { \  #define CHECK_MV8_CANDIDATE(X,Y) { \
494    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
# Line 464  Line 530 
530                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
531                                          const int x, const int y,                                          const int x, const int y,
532                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
533                                            const uint32_t iQuant,
534                                            const uint32_t iFcode,
535                                          MBParam * const pParam,                                          MBParam * const pParam,
536                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
537                                            const MACROBLOCK * const prevMBs,
538                                          VECTOR * const currMV,                                          VECTOR * const currMV,
539                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
540  {  {
541          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
542          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
543          int32_t iSAD;          int32_t iSAD;
544          int32_t pred_x,pred_y;          int32_t pred_x,pred_y;
# Line 493  Line 561 
561  }  }
562  */  */
563    
564  int32_t PMVfastSearch16_MainSearch(  int32_t Diamond16_MainSearch(
565                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
566                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
567                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 550  Line 618 
618          return iMinSAD;          return iMinSAD;
619  }  }
620    
621  int32_t PMVfastSearch16_Refine(  int32_t Square16_MainSearch(
622                                            const uint8_t * const pRef,
623                                            const uint8_t * const pRefH,
624                                            const uint8_t * const pRefV,
625                                            const uint8_t * const pRefHV,
626                                            const uint8_t * const cur,
627                                            const int x, const int y,
628                                            int32_t startx, int32_t starty,
629                                            int32_t iMinSAD,
630                                            VECTOR * const currMV,
631                                            const VECTOR * const pmv,
632                                            const int32_t min_dx, const int32_t max_dx,
633                                            const int32_t min_dy, const int32_t max_dy,
634                                            const int32_t iEdgedWidth,
635                                            const int32_t iDiamondSize,
636                                            const int32_t iFcode,
637                                            const int32_t iQuant,
638                                            int iFound)
639    {
640    /* Do a square search around given starting point, return SAD of best */
641    
642            int32_t iDirection=0;
643            int32_t iSAD;
644            VECTOR backupMV;
645            backupMV.x = startx;
646            backupMV.y = starty;
647    
648    /* It's one search with full square pattern, and new parts for all following diamonds */
649    
650    /*   new direction are extra, so 1-4 is normal diamond
651          537
652          1*2
653          648
654    */
655    
656            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
657            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
658            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
659            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
660    
661            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
662            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
663            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
664            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
665    
666    
667            if (iDirection)
668                    while (!iFound)
669                    {
670                            iFound = 1;
671                            backupMV=*currMV;
672    
673                            switch (iDirection)
674                            {
675                                    case 1:
676                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
677                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
678                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
679                                            break;
680                                    case 2:
681                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
682                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
683                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
684                                            break;
685    
686                                    case 3:
687                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
688                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
689                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
690                                            break;
691    
692                                    case 4:
693                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
694                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
695                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
696                                            break;
697    
698                                    case 5:
699                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
700                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
701                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
702                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
703                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
704                                            break;
705    
706                                    case 6:
707                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
708                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
709    
710                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
711                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
712                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
713    
714                                            break;
715    
716                                    case 7:
717                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
718                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
719                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
720                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
721                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
722                                            break;
723    
724                                    case 8:
725                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
726                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
727                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
728                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
729                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
730                                            break;
731                            default:
732                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
733                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
734                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
735                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
736    
737                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
738                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
739                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
740                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
741                                            break;
742                            }
743                    }
744            else
745                    {
746                            currMV->x = startx;
747                            currMV->y = starty;
748                    }
749            return iMinSAD;
750    }
751    
752    
753    int32_t Full16_MainSearch(
754                                            const uint8_t * const pRef,
755                                            const uint8_t * const pRefH,
756                                            const uint8_t * const pRefV,
757                                            const uint8_t * const pRefHV,
758                                            const uint8_t * const cur,
759                                            const int x, const int y,
760                                            int32_t startx, int32_t starty,
761                                            int32_t iMinSAD,
762                                            VECTOR * const currMV,
763                                            const VECTOR * const pmv,
764                                            const int32_t min_dx, const int32_t max_dx,
765                                            const int32_t min_dy, const int32_t max_dy,
766                                            const int32_t iEdgedWidth,
767                                            const int32_t iDiamondSize,
768                                            const int32_t iFcode,
769                                            const int32_t iQuant,
770                                            int iFound)
771    {
772            int32_t iSAD;
773            int32_t dx,dy;
774            VECTOR backupMV;
775            backupMV.x = startx;
776            backupMV.y = starty;
777    
778            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
779                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
780                            NOCHECK_MV16_CANDIDATE(dx,dy);
781    
782            return iMinSAD;
783    }
784    
785    int32_t Full8_MainSearch(
786                                            const uint8_t * const pRef,
787                                            const uint8_t * const pRefH,
788                                            const uint8_t * const pRefV,
789                                            const uint8_t * const pRefHV,
790                                            const uint8_t * const cur,
791                                            const int x, const int y,
792                                            int32_t startx, int32_t starty,
793                                            int32_t iMinSAD,
794                                            VECTOR * const currMV,
795                                            const VECTOR * const pmv,
796                                            const int32_t min_dx, const int32_t max_dx,
797                                            const int32_t min_dy, const int32_t max_dy,
798                                            const int32_t iEdgedWidth,
799                                            const int32_t iDiamondSize,
800                                            const int32_t iFcode,
801                                            const int32_t iQuant,
802                                            int iFound)
803    {
804            int32_t iSAD;
805            int32_t dx,dy;
806            VECTOR backupMV;
807            backupMV.x = startx;
808            backupMV.y = starty;
809    
810            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
811                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
812                            NOCHECK_MV8_CANDIDATE(dx,dy);
813    
814            return iMinSAD;
815    }
816    
817    
818    
819    int32_t Halfpel16_Refine(
820                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
821                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
822                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 585  Line 851 
851    
852  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
853    
854    
855  int32_t PMVfastSearch16(  int32_t PMVfastSearch16(
856                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
857                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
# Line 593  Line 860 
860                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
861                                          const int x, const int y,                                          const int x, const int y,
862                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
863                                          MBParam * const pParam,                                          const uint32_t iQuant,
864                                          MACROBLOCK * const pMBs,                                          const uint32_t iFcode,
865                                            const MBParam * const pParam,
866                                            const MACROBLOCK * const pMBs,
867                                            const MACROBLOCK * const prevMBs,
868                                          VECTOR * const currMV,                                          VECTOR * const currMV,
869                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
870  {  {
871          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;  
872          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
873          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
874          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 622  Line 890 
890          VECTOR pmv[4];          VECTOR pmv[4];
891          int32_t psad[4];          int32_t psad[4];
892    
893          MACROBLOCK * const pMB = pMBs + x + y * iWcount;          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
894            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
895    
896          static int32_t threshA,threshB;          static int32_t threshA,threshB;
897          int32_t bPredEq;          int32_t bPredEq;
# Line 666  Line 935 
935          If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2          If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
936  */  */
937    
938          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )          if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) )
939                  iFound=2;                  iFound=2;
940    
941  /* 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 720  Line 989 
989                  iEdgedWidth, MV_MAX_ERROR);                  iEdgedWidth, MV_MAX_ERROR);
990          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;
991    
992          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
993                  {                  {
994    
995                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
996                                  goto step10b;                          goto PMVfast16_Terminate_without_Refine;
997                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
998                                  goto step10;                          goto PMVfast16_Terminate_with_Refine;
999                  }                  }
1000    
1001  /*  /*
# Line 741  Line 1010 
1010          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1011    
1012  // previous frame MV is always possible  // previous frame MV is always possible
1013          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1014    
1015  // left neighbour, if allowed  // left neighbour, if allowed
1016          if (x != 0)          if (x != 0)
# Line 763  Line 1032 
1032                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1033    
1034  // top right neighbour, if allowed  // top right neighbour, if allowed
1035                  if (x != (iWcount-1))                  if ((uint32_t)x != (iWcount-1))
1036                  {                  {
1037                          if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!(MotionFlags & PMV_HALFPEL16 ))
1038                          {       pmv[3].x = EVEN(pmv[3].x);                          {       pmv[3].x = EVEN(pmv[3].x);
# Line 777  Line 1046 
1046     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.
1047  */  */
1048    
1049          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1050                  {                  {
1051                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1052                                  goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1053                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
1054                                  goto step10;                          goto PMVfast16_Terminate_with_Refine;
1055                  }                  }
1056    
1057    
# Line 799  Line 1068 
1068          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1069    
1070  /* 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 */
1071          iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1072                  x, y,                  x, y,
1073                  currMV->x, currMV->y, iMinSAD, &newMV,                  currMV->x, currMV->y, iMinSAD, &newMV,
1074                  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 1084 
1084  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1085    
1086                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1087                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1088                                  x, y,                                  x, y,
1089                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1090                          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 1097 
1097                  }                  }
1098    
1099                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1100                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1101                                  x, y,                                  x, y,
1102                          0, 0, iMinSAD, &newMV,                          0, 0, iMinSAD, &newMV,
1103                          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 1114 
1114          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.
1115  */  */
1116    
1117  step10:  PMVfast16_Terminate_with_Refine:
1118          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1119                  iMinSAD = PMVfastSearch16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1120                                  x, y,                                  x, y,
1121                                  currMV, iMinSAD,                                  currMV, iMinSAD,
1122                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1123    
1124  step10b:  PMVfast16_Terminate_without_Refine:
1125          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1126          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1127          return iMinSAD;          return iMinSAD;
# Line 863  Line 1132 
1132    
1133    
1134    
1135  int32_t PMVfastSearch8_MainSearch(  int32_t Diamond8_MainSearch(
1136                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
1137                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1138                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 920  Line 1189 
1189          return iMinSAD;          return iMinSAD;
1190  }  }
1191    
1192  int32_t PMVfastSearch8_Refine(  int32_t Halfpel8_Refine(
1193                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
1194                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1195                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 963  Line 1232 
1232                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1233                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1234                                          const int x, const int y,                                          const int x, const int y,
1235                                          const int start_x, int start_y,                                          const int start_x, const int start_y,
1236                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1237                                          MBParam * const pParam,                                          const uint32_t iQuant,
1238                                          MACROBLOCK * const pMBs,                                          const uint32_t iFcode,
1239                                            const MBParam * const pParam,
1240                                            const MACROBLOCK * const pMBs,
1241                                            const MACROBLOCK * const prevMBs,
1242                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1243                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1244  {  {
1245          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;  
1246          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1247          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1248          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 992  Line 1261 
1261          VECTOR newMV;          VECTOR newMV;
1262          VECTOR backupMV;          VECTOR backupMV;
1263    
1264          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1265            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1266    
1267          static int32_t threshA,threshB;          static int32_t threshA,threshB;
1268          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
# Line 1071  Line 1341 
1341                  iEdgedWidth);                  iEdgedWidth);
1342          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;
1343    
1344          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1345                  {                  {
1346                          if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1347                                  goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1348                          if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1349                                  goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1350                  }                  }
1351    
1352    
1353  /*  /*
1354  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.
1355          Also calculate (0,0) but do not subtract offset.          Also calculate (0,0) but do not subtract offset.
# Line 1129  Line 1400 
1400     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.
1401  */  */
1402    
1403          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1404                  {                  {
1405                          if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1406                                  goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1407                          if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1408                                  goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1409                  }                  }
1410    
1411  /************ (Diamond Search)  **************/  /************ (Diamond Search)  **************/
# Line 1150  Line 1421 
1421          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1422    
1423  /* 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 */
1424          iSAD = PMVfastSearch8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1425                  x, y,                  x, y,
1426                  currMV->x, currMV->y, iMinSAD, &newMV,                  currMV->x, currMV->y, iMinSAD, &newMV,
1427                  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 1437 
1437  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1438    
1439                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1440                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1441                                  x, y,                                  x, y,
1442                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1443                          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 1450 
1450                  }                  }
1451    
1452                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1453                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1454                                  x, y,                                  x, y,
1455                          0, 0, iMinSAD, &newMV,                          0, 0, iMinSAD, &newMV,
1456                          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 1467 
1467           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.
1468  */  */
1469    
1470  step10_8:  PMVfast8_Terminate_with_Refine:
1471          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1472                  iMinSAD = PMVfastSearch8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1473                                                     x, y,
1474                                                     currMV, iMinSAD,
1475                                                     pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1476    
1477    
1478    PMVfast8_Terminate_without_Refine:
1479            currPMV->x = currMV->x - pmv[0].x;
1480            currPMV->y = currMV->y - pmv[0].y;
1481    
1482            return iMinSAD;
1483    }
1484    
1485    int32_t EPZSSearch16(
1486                                            const uint8_t * const pRef,
1487                                            const uint8_t * const pRefH,
1488                                            const uint8_t * const pRefV,
1489                                            const uint8_t * const pRefHV,
1490                                            const IMAGE * const pCur,
1491                                            const int x, const int y,
1492                                            const uint32_t MotionFlags,
1493                                            const uint32_t iQuant,
1494                                            const uint32_t iFcode,
1495                                            const MBParam * const pParam,
1496                                            const MACROBLOCK * const pMBs,
1497                                            const MACROBLOCK * const prevMBs,
1498                                            VECTOR * const currMV,
1499                                            VECTOR * const currPMV)
1500    {
1501        const uint32_t iWcount = pParam->mb_width;
1502        const uint32_t iHcount = pParam->mb_height;
1503    
1504            const int32_t iWidth = pParam->width;
1505            const int32_t iHeight = pParam->height;
1506            const int32_t iEdgedWidth = pParam->edged_width;
1507    
1508            const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
1509    
1510            int32_t min_dx;
1511            int32_t max_dx;
1512            int32_t min_dy;
1513            int32_t max_dy;
1514    
1515            VECTOR newMV;
1516            VECTOR backupMV;
1517    
1518            VECTOR pmv[4];
1519            int32_t psad[8];
1520    
1521            static MACROBLOCK * oldMBs = NULL;
1522            const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1523            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1524            MACROBLOCK * oldMB = NULL;
1525    
1526            static int32_t thresh2;
1527            int32_t bPredEq;
1528            int32_t iMinSAD,iSAD=9999;
1529    
1530            MainSearch16FuncPtr EPZSMainSearchPtr;
1531    
1532            if (oldMBs == NULL)
1533            {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));
1534                    fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1535            }
1536            oldMB = oldMBs + x + y * iWcount;
1537    
1538    /* Get maximum range */
1539            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1540                            x, y, 16, iWidth, iHeight, iFcode);
1541    
1542    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1543    
1544            if (!(MotionFlags & PMV_HALFPEL16 ))
1545            { min_dx = EVEN(min_dx);
1546              max_dx = EVEN(max_dx);
1547              min_dy = EVEN(min_dy);
1548              max_dy = EVEN(max_dy);
1549            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1550    
1551            bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1552    
1553    /* Step 4: Calculate SAD around the Median prediction.
1554            MinSAD=SAD
1555            If Motion Vector equal to Previous frame motion vector
1556                    and MinSAD<PrevFrmSAD goto Step 10.
1557            If SAD<=256 goto Step 10.
1558    */
1559    
1560    // Prepare for main loop
1561    
1562            *currMV=pmv[0];         /* current best := median prediction */
1563            if (!(MotionFlags & PMV_HALFPEL16))
1564            {
1565                    currMV->x = EVEN(currMV->x);
1566                    currMV->y = EVEN(currMV->y);
1567            }
1568    
1569            if (currMV->x > max_dx)
1570                    currMV->x=max_dx;
1571            if (currMV->x < min_dx)
1572                    currMV->x=min_dx;
1573            if (currMV->y > max_dy)
1574                    currMV->y=max_dy;
1575            if (currMV->y < min_dy)
1576                    currMV->y=min_dy;
1577    
1578    /***************** This is predictor SET A: only median prediction ******************/
1579    
1580            iMinSAD = sad16( cur,
1581                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1582                    iEdgedWidth, MV_MAX_ERROR);
1583            iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
1584    
1585    // thresh1 is fixed to 256
1586            if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1587                    {
1588                            if (MotionFlags & PMV_QUICKSTOP16)
1589                                    goto EPZS16_Terminate_without_Refine;
1590                            if (MotionFlags & PMV_EARLYSTOP16)
1591                                    goto EPZS16_Terminate_with_Refine;
1592                    }
1593    
1594    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1595    
1596    // previous frame MV
1597            CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);
1598    
1599    // set threshhold based on Min of Prediction and SAD of collocated block
1600    // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
1601    
1602            if ((x==0) && (y==0) )
1603            {
1604                    thresh2 =  512;
1605            }
1606            else
1607            {
1608    /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
1609    
1610                    thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
1611            }
1612    
1613    // MV=(0,0) is often a good choice
1614    
1615            CHECK_MV16_ZERO;
1616    
1617    
1618    // left neighbour, if allowed
1619            if (x != 0)
1620            {
1621                    if (!(MotionFlags & PMV_HALFPEL16 ))
1622                    {       pmv[1].x = EVEN(pmv[1].x);
1623                            pmv[1].y = EVEN(pmv[1].y);
1624                    }
1625                    CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1626            }
1627    
1628    // top neighbour, if allowed
1629            if (y != 0)
1630            {
1631                    if (!(MotionFlags & PMV_HALFPEL16 ))
1632                    {       pmv[2].x = EVEN(pmv[2].x);
1633                            pmv[2].y = EVEN(pmv[2].y);
1634                    }
1635                    CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1636    
1637    // top right neighbour, if allowed
1638                    if ((uint32_t)x != (iWcount-1))
1639                    {
1640                            if (!(MotionFlags & PMV_HALFPEL16 ))
1641                            {       pmv[3].x = EVEN(pmv[3].x);
1642                                    pmv[3].y = EVEN(pmv[3].y);
1643                            }
1644                            CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
1645                    }
1646            }
1647    
1648    /* Terminate if MinSAD <= T_2
1649       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1650    */
1651    
1652            if ( (iMinSAD <= thresh2)
1653                    || ( MVequal(*currMV,pMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )
1654                    {
1655                            if (MotionFlags & PMV_QUICKSTOP16)
1656                                    goto EPZS16_Terminate_without_Refine;
1657                            if (MotionFlags & PMV_EARLYSTOP16)
1658                                    goto EPZS16_Terminate_with_Refine;
1659                    }
1660    
1661    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1662    
1663            backupMV = pMB->mvs[0];                 // last MV
1664            backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X
1665            backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y
1666    
1667            CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
1668    
1669    // left neighbour
1670            if (x != 0)
1671                    CHECK_MV16_CANDIDATE((oldMB-1)->mvs[0].x,oldMB->mvs[0].y);
1672    
1673    // top neighbour
1674            if (y != 0)
1675                    CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);
1676    
1677    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
1678    
1679            if ((uint32_t)x != iWcount-1)
1680                    CHECK_MV16_CANDIDATE((pMB+1)->mvs[0].x,oldMB->mvs[0].y);
1681    
1682    // bottom neighbour, dito
1683            if ((uint32_t)y != iHcount-1)
1684                    CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);
1685    
1686    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
1687            if (iMinSAD <= thresh2)
1688                    {
1689                            if (MotionFlags & PMV_QUICKSTOP16)
1690                                    goto EPZS16_Terminate_without_Refine;
1691                            if (MotionFlags & PMV_EARLYSTOP16)
1692                                    goto EPZS16_Terminate_with_Refine;
1693                    }
1694    
1695    /************ (if Diamond Search)  **************/
1696    
1697            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1698    
1699    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1700    
1701            if (MotionFlags & PMV_USESQUARES16)
1702                    EPZSMainSearchPtr = Square16_MainSearch;
1703            else
1704                    EPZSMainSearchPtr = Diamond16_MainSearch;
1705    
1706            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1707                            x, y,
1708                            currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1709                            2, iFcode, iQuant, 0);
1710    
1711            if (iSAD < iMinSAD)
1712            {
1713                    *currMV = newMV;
1714                    iMinSAD = iSAD;
1715            }
1716    
1717    
1718            if (MotionFlags & PMV_EXTSEARCH16)
1719            {
1720    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1721    
1722                    if (!(MVequal(pmv[0],backupMV)) )
1723                    {
1724                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1725                                    x, y,
1726                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1727                                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1728                    }
1729    
1730                    if (iSAD < iMinSAD)
1731                    {
1732                            *currMV = newMV;
1733                            iMinSAD = iSAD;
1734                    }
1735    
1736                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1737                    {
1738                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1739                                    x, y,
1740                            0, 0, iMinSAD, &newMV,
1741                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, /*iDiamondSize*/ 2, iFcode, iQuant, 0);
1742    
1743                            if (iSAD < iMinSAD)
1744                            {
1745                                    *currMV = newMV;
1746                                    iMinSAD = iSAD;
1747                            }
1748                    }
1749            }
1750    
1751    /***************        Choose best MV found     **************/
1752    
1753    EPZS16_Terminate_with_Refine:
1754            if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1755                    iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1756                                  x, y,                                  x, y,
1757                                  currMV, iMinSAD,                                  currMV, iMinSAD,
1758                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1759    
1760  step10_8b:  EPZS16_Terminate_without_Refine:
1761    
1762            *oldMB = *pMB;
1763    
1764          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1765          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1766            return iMinSAD;
1767    }
1768    
1769    
1770    int32_t EPZSSearch8(
1771                                            const uint8_t * const pRef,
1772                                            const uint8_t * const pRefH,
1773                                            const uint8_t * const pRefV,
1774                                            const uint8_t * const pRefHV,
1775                                            const IMAGE * const pCur,
1776                                            const int x, const int y,
1777                                            const int start_x, const int start_y,
1778                                            const uint32_t MotionFlags,
1779                                            const uint32_t iQuant,
1780                                            const uint32_t iFcode,
1781                                            const MBParam * const pParam,
1782                                            const MACROBLOCK * const pMBs,
1783                                            const MACROBLOCK * const prevMBs,
1784                                            VECTOR * const currMV,
1785                                            VECTOR * const currPMV)
1786    {
1787        const uint32_t iWcount = pParam->mb_width;
1788            const int32_t iWidth = pParam->width;
1789            const int32_t iHeight = pParam->height;
1790            const int32_t iEdgedWidth = pParam->edged_width;
1791    
1792            const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
1793    
1794            int32_t iDiamondSize=1;
1795    
1796            int32_t min_dx;
1797            int32_t max_dx;
1798            int32_t min_dy;
1799            int32_t max_dy;
1800    
1801            VECTOR newMV;
1802            VECTOR backupMV;
1803    
1804            VECTOR pmv[4];
1805            int32_t psad[8];
1806    
1807            const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
1808    
1809            const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1810            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1811    
1812            int32_t bPredEq;
1813            int32_t iMinSAD,iSAD=9999;
1814    
1815            MainSearch8FuncPtr EPZSMainSearchPtr;
1816    
1817    /* Get maximum range */
1818            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1819                            x, y, 8, iWidth, iHeight, iFcode);
1820    
1821    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1822    
1823            if (!(MotionFlags & PMV_HALFPEL8 ))
1824            { min_dx = EVEN(min_dx);
1825              max_dx = EVEN(max_dx);
1826              min_dy = EVEN(min_dy);
1827              max_dy = EVEN(max_dy);
1828            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1829    
1830            bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);
1831    
1832    
1833    /* Step 4: Calculate SAD around the Median prediction.
1834            MinSAD=SAD
1835            If Motion Vector equal to Previous frame motion vector
1836                    and MinSAD<PrevFrmSAD goto Step 10.
1837            If SAD<=256 goto Step 10.
1838    */
1839    
1840    // Prepare for main loop
1841    
1842    
1843            if (!(MotionFlags & PMV_HALFPEL8))
1844            {
1845                    currMV->x = EVEN(currMV->x);
1846                    currMV->y = EVEN(currMV->y);
1847            }
1848    
1849            if (currMV->x > max_dx)
1850                    currMV->x=max_dx;
1851            if (currMV->x < min_dx)
1852                    currMV->x=min_dx;
1853            if (currMV->y > max_dy)
1854                    currMV->y=max_dy;
1855            if (currMV->y < min_dy)
1856                    currMV->y=min_dy;
1857    
1858    /***************** This is predictor SET A: only median prediction ******************/
1859    
1860    
1861            iMinSAD = sad8( cur,
1862                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1863                    iEdgedWidth);
1864            iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
1865    
1866    
1867    // thresh1 is fixed to 256
1868            if (iMinSAD < 256/4 )
1869                    {
1870                            if (MotionFlags & PMV_QUICKSTOP8)
1871                                    goto EPZS8_Terminate_without_Refine;
1872                            if (MotionFlags & PMV_EARLYSTOP8)
1873                                    goto EPZS8_Terminate_with_Refine;
1874                    }
1875    
1876    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1877    
1878    // previous frame MV
1879            CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);
1880    
1881    // MV=(0,0) is often a good choice
1882    
1883            CHECK_MV8_ZERO;
1884    
1885    /* Terminate if MinSAD <= T_2
1886       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1887    */
1888    
1889            if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */
1890                    {
1891                            if (MotionFlags & PMV_QUICKSTOP8)
1892                                    goto EPZS8_Terminate_without_Refine;
1893                            if (MotionFlags & PMV_EARLYSTOP8)
1894                                    goto EPZS8_Terminate_with_Refine;
1895                    }
1896    
1897    /************ (if Diamond Search)  **************/
1898    
1899            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1900    
1901            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1902                    iDiamondSize *= 2;
1903    
1904    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1905    
1906    //      if (MotionFlags & PMV_USESQUARES8)
1907    //              EPZSMainSearchPtr = Square8_MainSearch;
1908    //      else
1909                    EPZSMainSearchPtr = Diamond8_MainSearch;
1910    
1911            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1912                    x, y,
1913                    currMV->x, currMV->y, iMinSAD, &newMV,
1914                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1915                    iDiamondSize, iFcode, iQuant, 00);
1916    
1917    
1918            if (iSAD < iMinSAD)
1919            {
1920                    *currMV = newMV;
1921                    iMinSAD = iSAD;
1922            }
1923    
1924            if (MotionFlags & PMV_EXTSEARCH8)
1925            {
1926    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1927    
1928                    if (!(MVequal(pmv[0],backupMV)) )
1929                    {
1930                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1931                                    x, y,
1932                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1933                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
1934    
1935                            if (iSAD < iMinSAD)
1936                            {
1937                                    *currMV = newMV;
1938                                    iMinSAD = iSAD;
1939                            }
1940                    }
1941    
1942                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1943                    {
1944                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1945                                    x, y,
1946                            0, 0, iMinSAD, &newMV,
1947                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
1948    
1949                            if (iSAD < iMinSAD)
1950                            {
1951                                    *currMV = newMV;
1952                                    iMinSAD = iSAD;
1953                            }
1954                    }
1955            }
1956    
1957    /***************        Choose best MV found     **************/
1958    
1959    EPZS8_Terminate_with_Refine:
1960            if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1961                    iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1962                                    x, y,
1963                                    currMV, iMinSAD,
1964                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1965    
1966    EPZS8_Terminate_without_Refine:
1967    
1968            currPMV->x = currMV->x - pmv[0].x;
1969            currPMV->y = currMV->y - pmv[0].y;
1970          return iMinSAD;          return iMinSAD;
1971  }  }
1972    
1973    
1974    
1975    
1976    
1977    /* ***********************************************************
1978            bvop motion estimation
1979    // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
1980    ***************************************************************/
1981    
1982    /*
1983    void MotionEstimationBVOP(
1984                            MBParam * const pParam,
1985                            FRAMEINFO * const frame,
1986    
1987                            // forward (past) reference
1988                            const MACROBLOCK * const f_mbs,
1989                        const IMAGE * const f_ref,
1990                            const IMAGE * const f_refH,
1991                        const IMAGE * const f_refV,
1992                            const IMAGE * const f_refHV,
1993                            // backward (future) reference
1994                            const MACROBLOCK * const b_mbs,
1995                        const IMAGE * const b_ref,
1996                            const IMAGE * const b_refH,
1997                        const IMAGE * const b_refV,
1998                            const IMAGE * const b_refHV)
1999    {
2000        const uint32_t mb_width = pParam->mb_width;
2001        const uint32_t mb_height = pParam->mb_height;
2002            const int32_t edged_width = pParam->edged_width;
2003    
2004            int32_t i,j;
2005    
2006            int32_t f_sad16;
2007            int32_t b_sad16;
2008            int32_t i_sad16;
2009            int32_t d_sad16;
2010            int32_t best_sad;
2011    
2012            VECTOR pmv_dontcare;
2013    
2014            // note: i==horizontal, j==vertical
2015        for (j = 0; j < mb_height; j++)
2016            {
2017                    for (i = 0; i < mb_width; i++)
2018                    {
2019                            MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
2020                            const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
2021                            const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
2022    
2023                            if (b_mb->mode == MODE_INTER
2024                                    && b_mb->cbp == 0
2025                                    && b_mb->mvs[0].x == 0
2026                                    && b_mb->mvs[0].y == 0)
2027                            {
2028                                    mb->mode = MB_IGNORE;
2029                                    mb->mvs[0].x = 0;
2030                                    mb->mvs[0].y = 0;
2031                                    mb->b_mvs[0].x = 0;
2032                                    mb->b_mvs[0].y = 0;
2033                                    continue;
2034                            }
2035    
2036    
2037                            // forward search
2038                            f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2039                                                    &frame->image,
2040                                                    i, j,
2041                                                    frame->motion_flags,  frame->quant, frame->fcode,
2042                                                    pParam,
2043                                                    f_mbs,
2044                                                    &mb->mvs[0], &pmv_dontcare);    // ignore pmv
2045    
2046                            // backward search
2047                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2048                                                    &frame->image,
2049                                                    i, j,
2050                                                    frame->motion_flags,  frame->quant, frame->bcode,
2051                                                    pParam,
2052                                                    b_mbs,
2053                                                    &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv
2054    
2055                            // interpolate search (simple, but effective)
2056                            i_sad16 = sad16bi_c(
2057                                            frame->image.y + i*16 + j*16*edged_width,
2058                                            get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2059                                                    i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),
2060                                            get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2061                                                    i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),
2062                                            edged_width);
2063    
2064                            // TODO: direct search
2065                            // predictor + range of [-32,32]
2066                            d_sad16 = 65535;
2067    
2068    
2069                            if (f_sad16 < b_sad16)
2070                            {
2071                                    best_sad = f_sad16;
2072                                    mb->mode = MB_FORWARD;
2073                            }
2074                            else
2075                            {
2076                                    best_sad = b_sad16;
2077                                    mb->mode = MB_BACKWARD;
2078                            }
2079    
2080                            if (i_sad16 < best_sad)
2081                            {
2082                                    best_sad = i_sad16;
2083                                    mb->mode = MB_INTERPOLATE;
2084                            }
2085    
2086                            if (d_sad16 < best_sad)
2087                            {
2088                                    best_sad = d_sad16;
2089                                    mb->mode = MB_DIRECT;
2090                            }
2091    
2092                    }
2093            }
2094    }
2095    
2096    */

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

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