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

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

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