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

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

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

revision 248, Fri Jun 28 15:14:40 2002 UTC revision 344, Sat Jul 27 23:07:33 2002 UTC
# Line 1  Line 1 
1  /**************************************************************************  /**************************************************************************
2   *   *
3     *      XVID MPEG-4 VIDEO CODEC
4     *      motion estimation
5     *
6     *      This program is an implementation of a part of one or more MPEG-4
7     *      Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
8     *      to use this software module in hardware or software products are
9     *      advised that its use may infringe existing patents or copyrights, and
10     *      any such use would be at such party's own risk.  The original
11     *      developer of this software module and his/her company, and subsequent
12     *      editors and their companies, will have no liability for use of this
13     *      software or modifications or derivatives thereof.
14     *
15     *      This program is free software; you can redistribute it and/or modify
16     *      it under the terms of the GNU General Public License as published by
17     *      the Free Software Foundation; either version 2 of the License, or
18     *      (at your option) any later version.
19     *
20     *      This program is distributed in the hope that it will be useful,
21     *      but WITHOUT ANY WARRANTY; without even the implied warranty of
22     *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     *      GNU General Public License for more details.
24     *
25     *      You should have received a copy of the GNU General Public License
26     *      along with this program; if not, write to the Free Software
27     *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28     *
29     *************************************************************************/
30    
31    /**************************************************************************
32     *
33   *  Modifications:   *  Modifications:
34   *   *
35   *      01.05.2002      updated MotionEstimationBVOP   *      01.05.2002      updated MotionEstimationBVOP
# Line 47  Line 77 
77  #include "motion.h"  #include "motion.h"
78  #include "sad.h"  #include "sad.h"
79    
 // very large value  
 #define MV_MAX_ERROR    (4096 * 256)  
   
 // stop search if sdelta < THRESHOLD  
 #define MV16_THRESHOLD  192  
 #define MV8_THRESHOLD   56  
   
 #define NEIGH_MOVE_THRESH 0  
 // how much a block's MV must differ from his neighbour  
 // to be search for INTER4V. The more, the faster...  
   
 /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  
 /* nb  = vop pixels * 2^(bpp-8) */  
 #define MV16_00_BIAS    (128+1)  
 #define MV8_00_BIAS     (0)  
   
 /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */  
 #define MV16_INTER_BIAS 512  
   
 /* Parameters which control inter/inter4v decision */  
 #define IMV16X16                        5  
   
 /* vector map (vlc delta size) smoother parameters */  
 #define NEIGH_TEND_16X16        2  
 #define NEIGH_TEND_8X8          2  
   
 // fast ((A)/2)*2  
 #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  
   
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
 int32_t PMVfastSearch16(const uint8_t * const pRef,  
                                                 const uint8_t * const pRefH,  
                                                 const uint8_t * const pRefV,  
                                                 const uint8_t * const pRefHV,  
                                                 const IMAGE * const pCur,  
                                                 const int x,  
                                                 const int y,  
                                                 const uint32_t MotionFlags,  
                                                 const uint32_t iQuant,  
                                                 const uint32_t iFcode,  
                                                 const MBParam * const pParam,  
                                                 const MACROBLOCK * const pMBs,  
                                                 const MACROBLOCK * const prevMBs,  
                                                 VECTOR * const currMV,  
                                                 VECTOR * const currPMV);  
   
 int32_t EPZSSearch16(const uint8_t * const pRef,  
                                          const uint8_t * const pRefH,  
                                          const uint8_t * const pRefV,  
                                          const uint8_t * const pRefHV,  
                                          const IMAGE * const pCur,  
                                          const int x,  
                                          const int y,  
                                          const uint32_t MotionFlags,  
                                          const uint32_t iQuant,  
                                          const uint32_t iFcode,  
                                          const MBParam * const pParam,  
                                          const MACROBLOCK * const pMBs,  
                                          const MACROBLOCK * const prevMBs,  
                                          VECTOR * const currMV,  
                                          VECTOR * const currPMV);  
   
   
 int32_t PMVfastSearch8(const uint8_t * const pRef,  
                                            const uint8_t * const pRefH,  
                                            const uint8_t * const pRefV,  
                                            const uint8_t * const pRefHV,  
                                            const IMAGE * const pCur,  
                                            const int x,  
                                            const int y,  
                                            const int start_x,  
                                            const int start_y,  
                                            const uint32_t MotionFlags,  
                                            const uint32_t iQuant,  
                                            const uint32_t iFcode,  
                                            const MBParam * const pParam,  
                                            const MACROBLOCK * const pMBs,  
                                            const MACROBLOCK * const prevMBs,  
                                            VECTOR * const currMV,  
                                            VECTOR * const currPMV);  
   
 int32_t EPZSSearch8(const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x,  
                                         const int y,  
                                         const int start_x,  
                                         const int start_y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
   
 typedef int32_t(MainSearch16Func) (const uint8_t * const pRef,  
                                                                    const uint8_t * const pRefH,  
                                                                    const uint8_t * const pRefV,  
                                                                    const uint8_t * const pRefHV,  
                                                                    const uint8_t * const cur,  
                                                                    const int x,  
                                                                    const int y,  
                                                                    int32_t startx,  
                                                                    int32_t starty,  
                                                                    int32_t iMinSAD,  
                                                                    VECTOR * const currMV,  
                                                                    const VECTOR * const pmv,  
                                                                    const int32_t min_dx,  
                                                                    const int32_t max_dx,  
                                                                    const int32_t min_dy,  
                                                                    const int32_t max_dy,  
                                                                    const int32_t iEdgedWidth,  
                                                                    const int32_t iDiamondSize,  
                                                                    const int32_t iFcode,  
                                                                    const int32_t iQuant,  
                                                                    int iFound);  
   
 typedef MainSearch16Func *MainSearch16FuncPtr;  
80    
81    
 typedef int32_t(MainSearch8Func) (const uint8_t * const pRef,  
                                                                   const uint8_t * const pRefH,  
                                                                   const uint8_t * const pRefV,  
                                                                   const uint8_t * const pRefHV,  
                                                                   const uint8_t * const cur,  
                                                                   const int x,  
                                                                   const int y,  
                                                                   int32_t startx,  
                                                                   int32_t starty,  
                                                                   int32_t iMinSAD,  
                                                                   VECTOR * const currMV,  
                                                                   const VECTOR * const pmv,  
                                                                   const int32_t min_dx,  
                                                                   const int32_t max_dx,  
                                                                   const int32_t min_dy,  
                                                                   const int32_t max_dy,  
                                                                   const int32_t iEdgedWidth,  
                                                                   const int32_t iDiamondSize,  
                                                                   const int32_t iFcode,  
                                                                   const int32_t iQuant,  
                                                                   int iFound);  
   
 typedef MainSearch8Func *MainSearch8FuncPtr;  
   
82  static int32_t lambda_vec16[32] =       /* rounded values for lambda param for weight of motion bits as in modified H.26L */  static int32_t lambda_vec16[32] =       /* rounded values for lambda param for weight of motion bits as in modified H.26L */
83  { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),  { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),
84                  (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),                  (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),
# Line 274  Line 155 
155                                                                                                     mv_bits(dy, iFcode));                                                                                                     mv_bits(dy, iFcode));
156  }  }
157    
   
   
   
   
 #ifndef SEARCH16  
 #define SEARCH16        PMVfastSearch16  
 //#define SEARCH16  FullSearch16  
 //#define SEARCH16  EPZSSearch16  
 #endif  
   
 #ifndef SEARCH8  
 #define SEARCH8         PMVfastSearch8  
 //#define SEARCH8   EPZSSearch8  
 #endif  
   
158  bool  bool
159  MotionEstimation(MBParam * const pParam,  MotionEstimation(MBParam * const pParam,
160                                   FRAMEINFO * const current,                                   FRAMEINFO * const current,
# Line 305  Line 171 
171          const IMAGE *const pCurrent = &current->image;          const IMAGE *const pCurrent = &current->image;
172          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
173    
174          const VECTOR zeroMV = { 0, 0 };          static const VECTOR zeroMV = { 0, 0 };
175            VECTOR predMV;
176    
177          int32_t x, y;          int32_t x, y;
178          int32_t iIntra = 0;          int32_t iIntra = 0;
# Line 314  Line 181 
181          if (sadInit)          if (sadInit)
182                  (*sadInit) ();                  (*sadInit) ();
183    
184          for (y = 0; y < iHcount; y++)          for (y = 0; y < iHcount; y++)   {
185                  for (x = 0; x < iWcount; x++) {                  for (x = 0; x < iWcount; x++) {
186    
187                          MACROBLOCK *const pMB = &pMBs[x + y * iWcount];                          MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
188    
189                            predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
190    
191                          pMB->sad16 =                          pMB->sad16 =
192                                  SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                                  SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
193                                                   y, current->motion_flags, current->quant,                                                   x, y, predMV.x, predMV.y, predMV.x, predMV.y,
194                                                     current->motion_flags, current->quant,
195                                                   current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,                                                   current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
196                                                   &pMB->pmvs[0]);                                                   &pMB->pmvs[0]);
197    
# Line 352  Line 223 
223                                           pMB->dquant == NO_CHANGE)) {                                           pMB->dquant == NO_CHANGE)) {
224                                          int32_t sad8 = IMV16X16 * current->quant;                                          int32_t sad8 = IMV16X16 * current->quant;
225    
226                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16) {
   
227                                                  sad8 += pMB->sad8[0] =                                                  sad8 += pMB->sad8[0] =
228                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
229                                                                          pCurrent, 2 * x, 2 * y, pMB->mv16.x,                                                                          pCurrent, 2 * x, 2 * y,
230                                                                          pMB->mv16.y, current->motion_flags,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
231                                                                            current->motion_flags,
232                                                                          current->quant, current->fcode, pParam,                                                                          current->quant, current->fcode, pParam,
233                                                                          pMBs, prevMBs, &pMB->mvs[0],                                                                          pMBs, prevMBs, &pMB->mvs[0],
234                                                                          &pMB->pmvs[0]);                                                                          &pMB->pmvs[0]);
235                                            }
236                                            if (sad8 < pMB->sad16) {
237    
238                                          if (sad8 < pMB->sad16)                                                  predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
239                                                  sad8 += pMB->sad8[1] =                                                  sad8 += pMB->sad8[1] =
240                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
241                                                                          pCurrent, 2 * x + 1, 2 * y, pMB->mv16.x,                                                                          pCurrent, 2 * x + 1, 2 * y,
242                                                                          pMB->mv16.y, current->motion_flags,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
243                                                                            current->motion_flags,
244                                                                          current->quant, current->fcode, pParam,                                                                          current->quant, current->fcode, pParam,
245                                                                          pMBs, prevMBs, &pMB->mvs[1],                                                                          pMBs, prevMBs, &pMB->mvs[1],
246                                                                          &pMB->pmvs[1]);                                                                          &pMB->pmvs[1]);
247                                            }
248                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16) {
249                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
250                                                  sad8 += pMB->sad8[2] =                                                  sad8 += pMB->sad8[2] =
251                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
252                                                                          pCurrent, 2 * x, 2 * y + 1, pMB->mv16.x,                                                                          pCurrent, 2 * x, 2 * y + 1,
253                                                                          pMB->mv16.y, current->motion_flags,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
254                                                                            current->motion_flags,
255                                                                          current->quant, current->fcode, pParam,                                                                          current->quant, current->fcode, pParam,
256                                                                          pMBs, prevMBs, &pMB->mvs[2],                                                                          pMBs, prevMBs, &pMB->mvs[2],
257                                                                          &pMB->pmvs[2]);                                                                          &pMB->pmvs[2]);
258                                            }
259                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16) {
260                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
261                                                  sad8 += pMB->sad8[3] =                                                  sad8 += pMB->sad8[3] =
262                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
263                                                                          pCurrent, 2 * x + 1, 2 * y + 1,                                                                          pCurrent, 2 * x + 1, 2 * y + 1,
264                                                                          pMB->mv16.x, pMB->mv16.y,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
265                                                                          current->motion_flags, current->quant,                                                                          current->motion_flags,
266                                                                          current->fcode, pParam, pMBs, prevMBs,                                                                          current->quant, current->fcode, pParam,
267                                                                          &pMB->mvs[3], &pMB->pmvs[3]);                                                                          pMBs, prevMBs,
268                                                                            &pMB->mvs[3],
269                                                                            &pMB->pmvs[3]);
270                                            }
271    
272                                          /* decide: MODE_INTER or MODE_INTER4V                                          /* decide: MODE_INTER or MODE_INTER4V
273                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
# Line 409  Line 289 
289                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
290                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
291                                  pMB->sad16;                                  pMB->sad16;
   
292                  }                  }
293                            }
294    
295          return 0;          return 0;
296  }  }
297    
298    
299  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
300    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
301      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
302    { \    { \
303      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \
304      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
305      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
306      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
307  }  }
308    
309  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
310      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
311      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
312      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
313      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
314  }  }
# Line 436  Line 318 
318      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
319    { \    { \
320      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
321      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
322      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
323      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
324  }  }
# Line 446  Line 328 
328      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
329    { \    { \
330      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
331      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
332      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
333      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
334  }  }
# Line 456  Line 338 
338      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
339    { \    { \
340      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
341      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
342      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
343      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
344  }  }
# Line 464  Line 346 
346    
347  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
348    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \
349    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\    iSAD += calc_delta_8(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
350    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
351    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
352  }  }
# Line 472  Line 354 
354  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
355    { \    { \
356      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
357      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
358      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
359      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
360  }  }
# Line 482  Line 364 
364      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
365    { \    { \
366      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
367      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
368      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
369      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
370  }  }
# Line 492  Line 374 
374      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
375    { \    { \
376      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
377      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
378      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
379      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
380  }  }
# Line 502  Line 384 
384      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
385    { \    { \
386      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
387      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
388      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
389      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
390  }  }
# Line 528  Line 410 
410          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
411          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
412          int32_t iSAD;          int32_t iSAD;
413          int32_t pred_x,pred_y;          VECTOR pred;
414    
415    
416          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
417    
418          iSAD = sad16( cur,          iSAD = sad16( cur,
419                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
# Line 540  Line 423 
423    
424          currMV->x = 0;          currMV->x = 0;
425          currMV->y = 0;          currMV->y = 0;
426          currPMV->x = -pred_x;          currPMV->x = -pred.x;
427          currPMV->y = -pred_y;          currPMV->y = -pred.y;
428    
429          return iSAD;          return iSAD;
430    
# Line 556  Line 439 
439                                           const uint8_t * const cur,                                           const uint8_t * const cur,
440                                           const int x,                                           const int x,
441                                           const int y,                                           const int y,
442                                           int32_t startx,                                     const int start_x,
443                                           int32_t starty,                                     const int start_y,
444                                           int32_t iMinSAD,                                     int iMinSAD,
445                                           VECTOR * const currMV,                                           VECTOR * const currMV,
446                                           const VECTOR * const pmv,                                     const int center_x,
447                                       const int center_y,
448                                           const int32_t min_dx,                                           const int32_t min_dx,
449                                           const int32_t max_dx,                                           const int32_t max_dx,
450                                           const int32_t min_dy,                                           const int32_t min_dy,
# Line 574  Line 458 
458  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
459    
460          int32_t iDirection = 0;          int32_t iDirection = 0;
461            int32_t iDirectionBackup;
462          int32_t iSAD;          int32_t iSAD;
463          VECTOR backupMV;          VECTOR backupMV;
464    
465          backupMV.x = startx;          backupMV.x = start_x;
466          backupMV.y = starty;          backupMV.y = start_y;
467    
468  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
469    
# Line 587  Line 472 
472          CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
473          CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
474    
475          if (iDirection)          if (iDirection) {
476                  while (!iFound) {                  while (!iFound) {
477                          iFound = 1;                          iFound = 1;
478                          backupMV = *currMV;                          backupMV = *currMV;
479                            iDirectionBackup = iDirection;
480    
481                          if (iDirection != 2)                          if (iDirectionBackup != 2)
482                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
483                                                                                     backupMV.y, 1);                                                                                     backupMV.y, 1);
484                          if (iDirection != 1)                          if (iDirectionBackup != 1)
485                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
486                                                                                     backupMV.y, 2);                                                                                     backupMV.y, 2);
487                          if (iDirection != 4)                          if (iDirectionBackup != 4)
488                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
489                                                                                     backupMV.y - iDiamondSize, 3);                                                                                     backupMV.y - iDiamondSize, 3);
490                          if (iDirection != 3)                          if (iDirectionBackup != 3)
491                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
492                                                                                     backupMV.y + iDiamondSize, 4);                                                                                     backupMV.y + iDiamondSize, 4);
493                    }
494          } else {          } else {
495                  currMV->x = startx;                  currMV->x = start_x;
496                  currMV->y = starty;                  currMV->y = start_y;
497          }          }
498          return iMinSAD;          return iMinSAD;
499  }  }
# Line 619  Line 506 
506                                          const uint8_t * const cur,                                          const uint8_t * const cur,
507                                          const int x,                                          const int x,
508                                          const int y,                                          const int y,
509                                          int32_t startx,                                     const int start_x,
510                                          int32_t starty,                                     const int start_y,
511                                          int32_t iMinSAD,                                     int iMinSAD,
512                                          VECTOR * const currMV,                                          VECTOR * const currMV,
513                                          const VECTOR * const pmv,                                     const int center_x,
514                                       const int center_y,
515                                          const int32_t min_dx,                                          const int32_t min_dx,
516                                          const int32_t max_dx,                                          const int32_t max_dx,
517                                          const int32_t min_dy,                                          const int32_t min_dy,
# Line 640  Line 528 
528          int32_t iSAD;          int32_t iSAD;
529          VECTOR backupMV;          VECTOR backupMV;
530    
531          backupMV.x = startx;          backupMV.x = start_x;
532          backupMV.y = starty;          backupMV.y = start_y;
533    
534  /* It's one search with full square pattern, and new parts for all following diamonds */  /* It's one search with full square pattern, and new parts for all following diamonds */
535    
# Line 781  Line 669 
669                                  break;                                  break;
670                          }                          }
671          } else {          } else {
672                  currMV->x = startx;                  currMV->x = start_x;
673                  currMV->y = starty;                  currMV->y = start_y;
674          }          }
675          return iMinSAD;          return iMinSAD;
676  }  }
# Line 796  Line 684 
684                                    const uint8_t * const cur,                                    const uint8_t * const cur,
685                                    const int x,                                    const int x,
686                                    const int y,                                    const int y,
687                                    int32_t startx,                                     const int start_x,
688                                    int32_t starty,                                     const int start_y,
689                                    int32_t iMinSAD,                                     int iMinSAD,
690                                    VECTOR * const currMV,                                    VECTOR * const currMV,
691                                    const VECTOR * const pmv,                                     const int center_x,
692                                       const int center_y,
693                                    const int32_t min_dx,                                    const int32_t min_dx,
694                                    const int32_t max_dx,                                    const int32_t max_dx,
695                                    const int32_t min_dy,                                    const int32_t min_dy,
# Line 815  Line 704 
704          int32_t dx, dy;          int32_t dx, dy;
705          VECTOR backupMV;          VECTOR backupMV;
706    
707          backupMV.x = startx;          backupMV.x = start_x;
708          backupMV.y = starty;          backupMV.y = start_y;
709    
710          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
711                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
# Line 833  Line 722 
722                                                  const uint8_t * const cur,                                                  const uint8_t * const cur,
723                                                  const int x,                                                  const int x,
724                                                  const int y,                                                  const int y,
725                                                  int32_t startx,                                             int start_x,
726                                                  int32_t starty,                                             int start_y,
727                                                  int32_t iMinSAD,                                             int iMinSAD,
728                                                  VECTOR * const currMV,                                                  VECTOR * const currMV,
729                                                  const VECTOR * const pmv,                                             const int center_x,
730                                               const int center_y,
731                                                  const int32_t min_dx,                                                  const int32_t min_dx,
732                                                  const int32_t max_dx,                                                  const int32_t max_dx,
733                                                  const int32_t min_dy,                                                  const int32_t min_dy,
# Line 854  Line 744 
744  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
745    
746          if (iDirection) {          if (iDirection) {
747                  CHECK_MV16_CANDIDATE(startx - iDiamondSize, starty);                  CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
748                  CHECK_MV16_CANDIDATE(startx + iDiamondSize, starty);                  CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
749                  CHECK_MV16_CANDIDATE(startx, starty - iDiamondSize);                  CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
750                  CHECK_MV16_CANDIDATE(startx, starty + iDiamondSize);                  CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
751          } else {          } else {
752                  int bDirection = 1 + 2 + 4 + 8;                  int bDirection = 1 + 2 + 4 + 8;
753    
754                  do {                  do {
755                          iDirection = 0;                          iDirection = 0;
756                          if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)                          if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
757                                  CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);                                  CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
758    
759                          if (bDirection & 2)                          if (bDirection & 2)
760                                  CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);                                  CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
761    
762                          if (bDirection & 4)                          if (bDirection & 4)
763                                  CHECK_MV16_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
764    
765                          if (bDirection & 8)                          if (bDirection & 8)
766                                  CHECK_MV16_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
767    
768                          /* now we're doing diagonal checks near our candidate */                          /* now we're doing diagonal checks near our candidate */
769    
# Line 881  Line 771 
771                          {                          {
772                                  bDirection = iDirection;                                  bDirection = iDirection;
773                                  iDirection = 0;                                  iDirection = 0;
774                                  startx = currMV->x;                                  start_x = currMV->x;
775                                  starty = currMV->y;                                  start_y = currMV->y;
776                                  if (bDirection & 3)     //our candidate is left or right                                  if (bDirection & 3)     //our candidate is left or right
777                                  {                                  {
778                                          CHECK_MV16_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);                                          CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
779                                          CHECK_MV16_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);                                          CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
780                                  } else                  // what remains here is up or down                                  } else                  // what remains here is up or down
781                                  {                                  {
782                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
783                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
784                                  }                                  }
785    
786                                  if (iDirection) {                                  if (iDirection) {
787                                          bDirection += iDirection;                                          bDirection += iDirection;
788                                          startx = currMV->x;                                          start_x = currMV->x;
789                                          starty = currMV->y;                                          start_y = currMV->y;
790                                  }                                  }
791                          } else                          //about to quit, eh? not so fast....                          } else                          //about to quit, eh? not so fast....
792                          {                          {
793                                  switch (bDirection) {                                  switch (bDirection) {
794                                  case 2:                                  case 2:
795                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
796                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
797                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
798                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
799                                          break;                                          break;
800                                  case 1:                                  case 1:
801                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,  
802                                                                                           starty - iDiamondSize, 1 + 4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
803                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                                                                           start_y - iDiamondSize, 1 + 4);
804                                                                                           starty + iDiamondSize, 1 + 8);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
805                                                                                             start_y + iDiamondSize, 1 + 8);
806                                          break;                                          break;
807                                  case 2 + 4:                                  case 2 + 4:
808                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
809                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
810                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
811                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
812                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
813                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
814                                          break;                                          break;
815                                  case 4:                                  case 4:
816                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
817                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
818                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
819                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
820                                          break;                                          break;
821                                  case 8:                                  case 8:
822                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
823                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
824                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
825                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
826                                          break;                                          break;
827                                  case 1 + 4:                                  case 1 + 4:
828                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
829                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
830                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
831                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
832                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
833                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
834                                          break;                                          break;
835                                  case 2 + 8:                                  case 2 + 8:
836                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
837                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
838                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
839                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
840                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
841                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
842                                          break;                                          break;
843                                  case 1 + 8:                                  case 1 + 8:
844                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
845                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
846                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
847                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
848                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
849                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
850                                          break;                                          break;
851                                  default:                //1+2+4+8 == we didn't find anything at all                                  default:                //1+2+4+8 == we didn't find anything at all
852                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
853                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
854                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
855                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
856                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
857                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
858                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
859                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
860                                          break;                                          break;
861                                  }                                  }
862                                  if (!iDirection)                                  if (!iDirection)
863                                          break;          //ok, the end. really                                          break;          //ok, the end. really
864                                  else {                                  else {
865                                          bDirection = iDirection;                                          bDirection = iDirection;
866                                          startx = currMV->x;                                          start_x = currMV->x;
867                                          starty = currMV->y;                                          start_y = currMV->y;
868                                  }                                  }
869                          }                          }
870                  }                  }
# Line 982  Line 873 
873          return iMinSAD;          return iMinSAD;
874  }  }
875    
876    
877    #define CHECK_MV16_F_INTERPOL(X,Y,BX,BY) { \
878      if ( ((X) <= max_dx) && ((X) >= min_dx) \
879        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
880      { \
881        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
882        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
883        if (iSAD < iMinSAD) \
884        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
885    }
886    
887    #define CHECK_MV16_F_INTERPOL_DIR(X,Y,BX,BY,D) { \
888      if ( ((X) <= max_dx) && ((X) >= min_dx) \
889        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
890      { \
891        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
892        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
893        if (iSAD < iMinSAD) \
894        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
895    }
896    
897    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y,BX,BY,D) { \
898      if ( ((X) <= max_dx) && ((X) >= min_dx) \
899        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
900      { \
901        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
902        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
903        if (iSAD < iMinSAD) \
904        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
905    }
906    
907    
908    #define CHECK_MV16_B_INTERPOL(FX,FY,X,Y) { \
909      if ( ((X) <= max_dx) && ((X) >= min_dx) \
910        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
911      { \
912        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
913        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
914        if (iSAD < iMinSAD) \
915        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
916    }
917    
918    
919    #define CHECK_MV16_B_INTERPOL_DIR(FX,FY,X,Y,D) { \
920      if ( ((X) <= max_dx) && ((X) >= min_dx) \
921        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
922      { \
923        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
924        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
925        if (iSAD < iMinSAD) \
926        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
927    }
928    
929    
930    #define CHECK_MV16_B_INTERPOL_FOUND(FX,FY,X,Y,D) { \
931      if ( ((X) <= max_dx) && ((X) >= min_dx) \
932        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
933      { \
934        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
935        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
936        if (iSAD < iMinSAD) \
937        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
938    }
939    
940    
941    #if (0==1)
942  int32_t  int32_t
943  AdvDiamond8_MainSearch(const uint8_t * const pRef,  Diamond16_InterpolMainSearch(
944                                             const uint8_t * const pRefH,                                          const uint8_t * const f_pRef,
945                                             const uint8_t * const pRefV,                                           const uint8_t * const f_pRefH,
946                                             const uint8_t * const pRefHV,                                           const uint8_t * const f_pRefV,
947                                             const uint8_t * const f_pRefHV,
948                                             const uint8_t * const cur,                                             const uint8_t * const cur,
949    
950                                            const uint8_t * const b_pRef,
951                                             const uint8_t * const b_pRefH,
952                                             const uint8_t * const b_pRefV,
953                                             const uint8_t * const b_pRefHV,
954    
955                                             const int x,                                             const int x,
956                                             const int y,                                             const int y,
957                                             int32_t startx,  
958                                             int32_t starty,                                     const int f_start_x,
959                                             int32_t iMinSAD,                                     const int f_start_y,
960                                             VECTOR * const currMV,                                     const int b_start_x,
961                                             const VECTOR * const pmv,                                     const int b_start_y,
962    
963                                       int iMinSAD,
964                                       VECTOR * const f_currMV,
965                                       VECTOR * const b_currMV,
966    
967                                       const int f_center_x,
968                                       const int f_center_y,
969                                       const int b_center_x,
970                                       const int b_center_y,
971    
972                                             const int32_t min_dx,                                             const int32_t min_dx,
973                                             const int32_t max_dx,                                             const int32_t max_dx,
974                                             const int32_t min_dy,                                             const int32_t min_dy,
975                                             const int32_t max_dy,                                             const int32_t max_dy,
976                                             const int32_t iEdgedWidth,                                             const int32_t iEdgedWidth,
977                                             const int32_t iDiamondSize,                                             const int32_t iDiamondSize,
978                                             const int32_t iFcode,  
979                                             const int32_t f_iFcode,
980                                             const int32_t b_iFcode,
981    
982                                             const int32_t iQuant,                                             const int32_t iQuant,
983                                             int iDirection)                                           int iFound)
984  {  {
985    /* Do a diamond search around given starting point, return SAD of best */
986    
987            int32_t f_iDirection = 0;
988            int32_t b_iDirection = 0;
989          int32_t iSAD;          int32_t iSAD;
990    
991  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */          VECTOR f_backupMV;
992            VECTOR b_backupMV;
         if (iDirection) {  
                 CHECK_MV8_CANDIDATE(startx - iDiamondSize, starty);  
                 CHECK_MV8_CANDIDATE(startx + iDiamondSize, starty);  
                 CHECK_MV8_CANDIDATE(startx, starty - iDiamondSize);  
                 CHECK_MV8_CANDIDATE(startx, starty + iDiamondSize);  
         } else {  
                 int bDirection = 1 + 2 + 4 + 8;  
   
                 do {  
                         iDirection = 0;  
                         if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)  
                                 CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);  
993    
994                          if (bDirection & 2)          f_backupMV.x = start_x;
995                                  CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);          f_backupMV.y = start_y;
996            b_backupMV.x = start_x;
997            b_backupMV.y = start_y;
998    
999                          if (bDirection & 4)  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
                                 CHECK_MV8_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);  
1000    
1001                          if (bDirection & 8)          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1002                                  CHECK_MV8_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);          CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1003            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1004            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1005    
1006                          /* now we're doing diagonal checks near our candidate */          if (iDirection)
1007                    while (!iFound) {
1008                            iFound = 1;
1009                            backupMV = *currMV;
1010    
1011                          if (iDirection)         //checking if anything found                          if (iDirection != 2)
1012                          {                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1013                                  bDirection = iDirection;                                                                                     backupMV.y, 1);
1014                            if (iDirection != 1)
1015                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1016                                                                                       backupMV.y, 2);
1017                            if (iDirection != 4)
1018                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1019                                                                                       backupMV.y - iDiamondSize, 3);
1020                            if (iDirection != 3)
1021                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1022                                                                                       backupMV.y + iDiamondSize, 4);
1023            } else {
1024                    currMV->x = start_x;
1025                    currMV->y = start_y;
1026            }
1027            return iMinSAD;
1028    }
1029    #endif
1030    
1031    
1032    int32_t
1033    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1034                                               const uint8_t * const pRefH,
1035                                               const uint8_t * const pRefV,
1036                                               const uint8_t * const pRefHV,
1037                                               const uint8_t * const cur,
1038                                               const int x,
1039                                               const int y,
1040                                               int start_x,
1041                                               int start_y,
1042                                               int iMinSAD,
1043                                               VECTOR * const currMV,
1044                                               const int center_x,
1045                                               const int center_y,
1046                                               const int32_t min_dx,
1047                                               const int32_t max_dx,
1048                                               const int32_t min_dy,
1049                                               const int32_t max_dy,
1050                                               const int32_t iEdgedWidth,
1051                                               const int32_t iDiamondSize,
1052                                               const int32_t iFcode,
1053                                               const int32_t iQuant,
1054                                               int iDirection)
1055    {
1056    
1057            int32_t iSAD;
1058    
1059    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1060    
1061            if (iDirection) {
1062                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1063                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1064                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1065                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1066            } else {
1067                    int bDirection = 1 + 2 + 4 + 8;
1068    
1069                    do {
1070                            iDirection = 0;
1071                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
1072                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1073    
1074                            if (bDirection & 2)
1075                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1076    
1077                            if (bDirection & 4)
1078                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1079    
1080                            if (bDirection & 8)
1081                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1082    
1083                            /* now we're doing diagonal checks near our candidate */
1084    
1085                            if (iDirection)         //checking if anything found
1086                            {
1087                                    bDirection = iDirection;
1088                                  iDirection = 0;                                  iDirection = 0;
1089                                  startx = currMV->x;                                  start_x = currMV->x;
1090                                  starty = currMV->y;                                  start_y = currMV->y;
1091                                  if (bDirection & 3)     //our candidate is left or right                                  if (bDirection & 3)     //our candidate is left or right
1092                                  {                                  {
1093                                          CHECK_MV8_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1094                                          CHECK_MV8_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1095                                  } else                  // what remains here is up or down                                  } else                  // what remains here is up or down
1096                                  {                                  {
1097                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1098                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1099                                  }                                  }
1100    
1101                                  if (iDirection) {                                  if (iDirection) {
1102                                          bDirection += iDirection;                                          bDirection += iDirection;
1103                                          startx = currMV->x;                                          start_x = currMV->x;
1104                                          starty = currMV->y;                                          start_y = currMV->y;
1105                                  }                                  }
1106                          } else                          //about to quit, eh? not so fast....                          } else                          //about to quit, eh? not so fast....
1107                          {                          {
1108                                  switch (bDirection) {                                  switch (bDirection) {
1109                                  case 2:                                  case 2:
1110                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1111                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1112                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1113                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1114                                          break;                                          break;
1115                                  case 1:                                  case 1:
1116                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1117                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1118                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1119                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1120                                          break;                                          break;
1121                                  case 2 + 4:                                  case 2 + 4:
1122                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1123                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1124                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1125                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1126                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1127                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1128                                          break;                                          break;
1129                                  case 4:                                  case 4:
1130                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1131                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1132                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1133                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1134                                          break;                                          break;
1135                                  case 8:                                  case 8:
1136                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1137                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1138                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1139                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1140                                          break;                                          break;
1141                                  case 1 + 4:                                  case 1 + 4:
1142                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1143                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1144                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1145                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1146                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1147                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1148                                          break;                                          break;
1149                                  case 2 + 8:                                  case 2 + 8:
1150                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1151                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1152                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1153                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1154                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1155                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1156                                          break;                                          break;
1157                                  case 1 + 8:                                  case 1 + 8:
1158                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1159                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1160                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1161                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1162                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1163                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1164                                          break;                                          break;
1165                                  default:                //1+2+4+8 == we didn't find anything at all                                  default:                //1+2+4+8 == we didn't find anything at all
1166                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1167                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1168                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1169                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1170                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1171                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1172                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1173                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1174                                          break;                                          break;
1175                                  }                                  }
1176                                  if (!(iDirection))                                  if (!(iDirection))
1177                                          break;          //ok, the end. really                                          break;          //ok, the end. really
1178                                  else {                                  else {
1179                                          bDirection = iDirection;                                          bDirection = iDirection;
1180                                          startx = currMV->x;                                          start_x = currMV->x;
1181                                          starty = currMV->y;                                          start_y = currMV->y;
1182                                  }                                  }
1183                          }                          }
1184                  }                  }
# Line 1148  Line 1196 
1196                                   const uint8_t * const cur,                                   const uint8_t * const cur,
1197                                   const int x,                                   const int x,
1198                                   const int y,                                   const int y,
1199                                   int32_t startx,                             const int start_x,
1200                                   int32_t starty,                             const int start_y,
1201                                   int32_t iMinSAD,                             int iMinSAD,
1202                                   VECTOR * const currMV,                                   VECTOR * const currMV,
1203                                   const VECTOR * const pmv,                             const int center_x,
1204                               const int center_y,
1205                                   const int32_t min_dx,                                   const int32_t min_dx,
1206                                   const int32_t max_dx,                                   const int32_t max_dx,
1207                                   const int32_t min_dy,                                   const int32_t min_dy,
# Line 1167  Line 1216 
1216          int32_t dx, dy;          int32_t dx, dy;
1217          VECTOR backupMV;          VECTOR backupMV;
1218    
1219          backupMV.x = startx;          backupMV.x = start_x;
1220          backupMV.y = starty;          backupMV.y = start_y;
1221    
1222          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1223                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
# Line 1177  Line 1226 
1226          return iMinSAD;          return iMinSAD;
1227  }  }
1228    
1229    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1230    
1231  int32_t  int32_t
1232  Halfpel16_Refine(const uint8_t * const pRef,  Halfpel16_Refine(const uint8_t * const pRef,
# Line 1189  Line 1238 
1238                                   const int y,                                   const int y,
1239                                   VECTOR * const currMV,                                   VECTOR * const currMV,
1240                                   int32_t iMinSAD,                                   int32_t iMinSAD,
1241                                   const VECTOR * const pmv,                             const int center_x,
1242                               const int center_y,
1243                                   const int32_t min_dx,                                   const int32_t min_dx,
1244                                   const int32_t max_dx,                                   const int32_t max_dx,
1245                                   const int32_t min_dy,                                   const int32_t min_dy,
# Line 1218  Line 1268 
1268  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1269    
1270    
1271    
1272  int32_t  int32_t
1273  PMVfastSearch16(const uint8_t * const pRef,  PMVfastSearch16(const uint8_t * const pRef,
1274                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
# Line 1226  Line 1277 
1277                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1278                                  const int x,                                  const int x,
1279                                  const int y,                                  const int y,
1280                                    const int start_x,
1281                                    const int start_y,
1282                                    const int center_x,
1283                                    const int center_y,
1284                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1285                                  const uint32_t iQuant,                                  const uint32_t iQuant,
1286                                  const uint32_t iFcode,                                  const uint32_t iFcode,
# Line 1259  Line 1314 
1314    
1315          MainSearch16FuncPtr MainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
1316    
 //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
1317          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1318    
1319          static int32_t threshA, threshB;          int32_t threshA, threshB;
1320          int32_t bPredEq;          int32_t bPredEq;
1321          int32_t iMinSAD, iSAD;          int32_t iMinSAD, iSAD;
1322    
# Line 1280  Line 1334 
1334          }          }
1335    
1336          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1337          bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad, 0, 0);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1338            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1339    
1340          if ((x == 0) && (y == 0)) {          if ((x == 0) && (y == 0)) {
1341                  threshA = 512;                  threshA = 512;
1342                  threshB = 1024;                  threshB = 1024;
   
1343          } else {          } else {
1344                  threshA = psad[0];                  threshA = psad[0];
1345                  threshB = threshA + 256;                  threshB = threshA + 256;
# Line 1306  Line 1360 
1360     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1361  */  */
1362    
1363          *currMV = pmv[0];                       /* current best := prediction */          currMV->x = start_x;
1364            currMV->y = start_y;
1365    
1366          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
1367                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1368                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
# Line 1330  Line 1386 
1386                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1387                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1388          iMinSAD +=          iMinSAD +=
1389                  calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1390                                            (uint8_t) iFcode, iQuant);                                            (uint8_t) iFcode, iQuant);
1391    
1392          if ((iMinSAD < 256) ||          if ((iMinSAD < 256) ||
1393                  ((MVequal(*currMV, prevMB->mvs[0])) &&                  ((MVequal(*currMV, prevMB->mvs[0])) &&
1394                   ((uint32_t) iMinSAD < prevMB->sad16))) {                   ((int32_t) iMinSAD < prevMB->sad16))) {
1395                  if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode                  if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1396                  {                  {
1397                          if (!MVzero(*currMV)) {                          if (!MVzero(*currMV)) {
# Line 1439  Line 1495 
1495    
1496          if ((iMinSAD <= threshA) ||          if ((iMinSAD <= threshA) ||
1497                  (MVequal(*currMV, prevMB->mvs[0]) &&                  (MVequal(*currMV, prevMB->mvs[0]) &&
1498                   ((uint32_t) iMinSAD < prevMB->sad16))) {                   ((int32_t) iMinSAD < prevMB->sad16))) {
1499                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1500                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1501                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1466  Line 1522 
1522    
1523          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
1524    
1525    
1526  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1527          iSAD =          iSAD =
1528                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1529                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1530                                                      min_dx, max_dx,
1531                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1532                                                    iQuant, iFound);                                                    iQuant, iFound);
1533    
# Line 1484  Line 1542 
1542                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
1543                          iSAD =                          iSAD =
1544                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1545                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1546                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1547                                                                    iDiamondSize, iFcode, iQuant, iFound);                                                                    iDiamondSize, iFcode, iQuant, iFound);
1548    
# Line 1497  Line 1555 
1555                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1556                          iSAD =                          iSAD =
1557                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1558                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y,
1559                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                                    min_dx, max_dx, min_dy, max_dy,
1560                                                                      iEdgedWidth, iDiamondSize, iFcode,
1561                                                                    iQuant, iFound);                                                                    iQuant, iFound);
1562    
1563                          if (iSAD < iMinSAD) {                          if (iSAD < iMinSAD) {
# Line 1516  Line 1575 
1575          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
1576                  iMinSAD =                  iMinSAD =
1577                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1578                                                           iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1579                                                           iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1580    
1581    PMVfast16_Terminate_without_Refine:    PMVfast16_Terminate_without_Refine:
1582          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1583          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1584          return iMinSAD;          return iMinSAD;
1585  }  }
1586    
# Line 1538  Line 1597 
1597                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1598                                          const int x,                                          const int x,
1599                                          const int y,                                          const int y,
1600                                          int32_t startx,                                          int32_t start_x,
1601                                          int32_t starty,                                          int32_t start_y,
1602                                          int32_t iMinSAD,                                          int32_t iMinSAD,
1603                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1604                                          const VECTOR * const pmv,                                     const int center_x,
1605                                       const int center_y,
1606                                          const int32_t min_dx,                                          const int32_t min_dx,
1607                                          const int32_t max_dx,                                          const int32_t max_dx,
1608                                          const int32_t min_dy,                                          const int32_t min_dy,
# Line 1556  Line 1616 
1616  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1617    
1618          int32_t iDirection = 0;          int32_t iDirection = 0;
1619            int32_t iDirectionBackup;
1620          int32_t iSAD;          int32_t iSAD;
1621          VECTOR backupMV;          VECTOR backupMV;
1622    
1623          backupMV.x = startx;          backupMV.x = start_x;
1624          backupMV.y = starty;          backupMV.y = start_y;
1625    
1626  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1627    
# Line 1569  Line 1630 
1630          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1631          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1632    
1633          if (iDirection)          if (iDirection) {
1634                  while (!iFound) {                  while (!iFound) {
1635                          iFound = 1;                          iFound = 1;
1636                          backupMV = *currMV;     // since iDirection!=0, this is well defined!                          backupMV = *currMV;     // since iDirection!=0, this is well defined!
1637                            iDirectionBackup = iDirection;
1638    
1639                          if (iDirection != 2)                          if (iDirectionBackup != 2)
1640                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1641                                                                                    backupMV.y, 1);                                                                                    backupMV.y, 1);
1642                          if (iDirection != 1)                          if (iDirectionBackup != 1)
1643                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1644                                                                                    backupMV.y, 2);                                                                                    backupMV.y, 2);
1645                          if (iDirection != 4)                          if (iDirectionBackup != 4)
1646                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1647                                                                                    backupMV.y - iDiamondSize, 3);                                                                                    backupMV.y - iDiamondSize, 3);
1648                          if (iDirection != 3)                          if (iDirectionBackup != 3)
1649                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1650                                                                                    backupMV.y + iDiamondSize, 4);                                                                                    backupMV.y + iDiamondSize, 4);
1651                    }
1652          } else {          } else {
1653                  currMV->x = startx;                  currMV->x = start_x;
1654                  currMV->y = starty;                  currMV->y = start_y;
1655          }          }
1656          return iMinSAD;          return iMinSAD;
1657  }  }
1658    
1659  int32_t  int32_t
1660  Halfpel8_Refine(const uint8_t * const pRef,  Halfpel8_Refine_c(const uint8_t * const pRef,
1661                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
1662                                  const uint8_t * const pRefV,                                  const uint8_t * const pRefV,
1663                                  const uint8_t * const pRefHV,                                  const uint8_t * const pRefHV,
# Line 1603  Line 1666 
1666                                  const int y,                                  const int y,
1667                                  VECTOR * const currMV,                                  VECTOR * const currMV,
1668                                  int32_t iMinSAD,                                  int32_t iMinSAD,
1669                                  const VECTOR * const pmv,                             const int center_x,
1670                               const int center_y,
1671                                  const int32_t min_dx,                                  const int32_t min_dx,
1672                                  const int32_t max_dx,                                  const int32_t max_dx,
1673                                  const int32_t min_dy,                                  const int32_t min_dy,
# Line 1642  Line 1706 
1706                             const int y,                             const int y,
1707                             const int start_x,                             const int start_x,
1708                             const int start_y,                             const int start_y,
1709                                    const int center_x,
1710                                    const int center_y,
1711                             const uint32_t MotionFlags,                             const uint32_t MotionFlags,
1712                             const uint32_t iQuant,                             const uint32_t iQuant,
1713                             const uint32_t iFcode,                             const uint32_t iFcode,
# Line 1674  Line 1740 
1740  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1741          const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;          const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
1742    
1743          static int32_t threshA, threshB;           int32_t threshA, threshB;
1744          int32_t iFound, bPredEq;          int32_t iFound, bPredEq;
1745          int32_t iMinSAD, iSAD;          int32_t iMinSAD, iSAD;
1746    
# Line 1698  Line 1764 
1764          }          }
1765    
1766          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1767          bPredEq =          //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
1768                  get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad, 0, 0);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
1769    
1770          if ((x == 0) && (y == 0)) {          if ((x == 0) && (y == 0)) {
1771                  threshA = 512 / 4;                  threshA = 512 / 4;
1772                  threshB = 1024 / 4;                  threshB = 1024 / 4;
1773    
1774          } else {          } else {
1775                  threshA = psad[0] / 4;  /* good estimate */                  threshA = psad[0] / 4;  /* good estimate? */
1776                  threshB = threshA + 256 / 4;                  threshB = threshA + 256 / 4;
1777                  if (threshA < 512 / 4)                  if (threshA < 512 / 4)
1778                          threshA = 512 / 4;                          threshA = 512 / 4;
# Line 1745  Line 1811 
1811                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
1812                                                  iEdgedWidth), iEdgedWidth);                                                  iEdgedWidth), iEdgedWidth);
1813          iMinSAD +=          iMinSAD +=
1814                  calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_8(currMV->x - center_x, currMV->y - center_y,
1815                                           (uint8_t) iFcode, iQuant);                                           (uint8_t) iFcode, iQuant);
1816    
1817          if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))          if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
1818                                                                  && ((uint32_t) iMinSAD <                                                                  && ((int32_t) iMinSAD <
1819                                                                          prevMB->sad8[iSubBlock]))) {                                                                          prevMB->sad8[iSubBlock]))) {
1820                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1821                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
# Line 1788  Line 1854 
1854  // the median prediction might be even better than mv16  // the median prediction might be even better than mv16
1855    
1856          if (!MVequal(pmv[0], startMV))          if (!MVequal(pmv[0], startMV))
1857                  CHECK_MV8_CANDIDATE(pmv[0].x, pmv[0].y);                  CHECK_MV8_CANDIDATE(center_x, center_y);
1858    
1859  // (0,0) if needed  // (0,0) if needed
1860          if (!MVzero(pmv[0]))          if (!MVzero(pmv[0]))
# Line 1804  Line 1870 
1870    
1871          if ((iMinSAD <= threshA) ||          if ((iMinSAD <= threshA) ||
1872                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1873                   ((uint32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {                   ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1874                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1875                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1876                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1863  Line 1929 
1929    
1930          if ((iMinSAD <= threshA) ||          if ((iMinSAD <= threshA) ||
1931                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1932                   ((uint32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {                   ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1933                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1934                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1935                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1885  Line 1951 
1951  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1952          iSAD =          iSAD =
1953                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
1954                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
1955                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1956                                                    iQuant, iFound);                                                    iQuant, iFound);
1957    
# Line 1900  Line 1966 
1966                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
1967                          iSAD =                          iSAD =
1968                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1969                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
1970                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1971                                                                    iDiamondSize, iFcode, iQuant, iFound);                                                                    iDiamondSize, iFcode, iQuant, iFound);
1972    
# Line 1913  Line 1979 
1979                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1980                          iSAD =                          iSAD =
1981                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1982                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
1983                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
1984                                                                    iQuant, iFound);                                                                    iQuant, iFound);
1985    
# Line 1932  Line 1998 
1998          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
1999                  iMinSAD =                  iMinSAD =
2000                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2001                                                          iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2002                                                          iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2003    
2004    
2005    PMVfast8_Terminate_without_Refine:    PMVfast8_Terminate_without_Refine:
2006          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2007          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2008    
2009          return iMinSAD;          return iMinSAD;
2010  }  }
# Line 1951  Line 2017 
2017                           const IMAGE * const pCur,                           const IMAGE * const pCur,
2018                           const int x,                           const int x,
2019                           const int y,                           const int y,
2020                            const int start_x,
2021                            const int start_y,
2022                            const int center_x,
2023                            const int center_y,
2024                           const uint32_t MotionFlags,                           const uint32_t MotionFlags,
2025                           const uint32_t iQuant,                           const uint32_t iQuant,
2026                           const uint32_t iFcode,                           const uint32_t iFcode,
# Line 1986  Line 2056 
2056          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2057          MACROBLOCK *oldMB = NULL;          MACROBLOCK *oldMB = NULL;
2058    
2059          static int32_t thresh2;           int32_t thresh2;
2060          int32_t bPredEq;          int32_t bPredEq;
2061          int32_t iMinSAD, iSAD = 9999;          int32_t iMinSAD, iSAD = 9999;
2062    
# Line 2009  Line 2079 
2079                  max_dy = EVEN(max_dy);                  max_dy = EVEN(max_dy);
2080          }          }
2081          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2082          bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad, 0, 0);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2083            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2084    
2085  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2086          MinSAD=SAD          MinSAD=SAD
# Line 2020  Line 2091 
2091    
2092  // Prepare for main loop  // Prepare for main loop
2093    
2094          *currMV = pmv[0];                       /* current best := median prediction */          currMV->x = start_x;
2095            currMV->y = start_y;
2096    
2097          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
2098                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2099                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
# Line 2042  Line 2115 
2115                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2116                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2117          iMinSAD +=          iMinSAD +=
2118                  calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2119                                            (uint8_t) iFcode, iQuant);                                            (uint8_t) iFcode, iQuant);
2120    
2121  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2122          if ((iMinSAD < 256) ||          if ((iMinSAD < 256) ||
2123                  ((MVequal(*currMV, prevMB->mvs[0])) &&                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2124                   ((uint32_t) iMinSAD < prevMB->sad16))) {                   ((int32_t) iMinSAD < prevMB->sad16))) {
2125                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2126                          goto EPZS16_Terminate_without_Refine;                          goto EPZS16_Terminate_without_Refine;
2127                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 2108  Line 2181 
2181    
2182          if ((iMinSAD <= thresh2)          if ((iMinSAD <= thresh2)
2183                  || (MVequal(*currMV, prevMB->mvs[0]) &&                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2184                          ((uint32_t) iMinSAD <= prevMB->sad16))) {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2185                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2186                          goto EPZS16_Terminate_without_Refine;                          goto EPZS16_Terminate_without_Refine;
2187                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 2154  Line 2227 
2227    
2228          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2229    
2230          if (MotionFlags & PMV_USESQUARES8)          if (MotionFlags & PMV_USESQUARES16)
2231                  MainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
2232          else          else
2233           if (MotionFlags & PMV_ADVANCEDDIAMOND8)           if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2234                  MainSearchPtr = AdvDiamond16_MainSearch;                  MainSearchPtr = AdvDiamond16_MainSearch;
2235          else          else
2236                  MainSearchPtr = Diamond16_MainSearch;                  MainSearchPtr = Diamond16_MainSearch;
# Line 2166  Line 2239 
2239    
2240          iSAD =          iSAD =
2241                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2242                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2243                                                    min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                    min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2244    
2245          if (iSAD < iMinSAD) {          if (iSAD < iMinSAD) {
# Line 2181  Line 2254 
2254                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
2255                          iSAD =                          iSAD =
2256                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2257                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2258                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2259                                                                    2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2260                  }                  }
# Line 2194  Line 2267 
2267                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2268                          iSAD =                          iSAD =
2269                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2270                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2271                                                                    max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2272    
2273                          if (iSAD < iMinSAD) {                          if (iSAD < iMinSAD) {
# Line 2210  Line 2283 
2283          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2284                  iMinSAD =                  iMinSAD =
2285                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2286                                                           iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2287                                                           iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
2288    
2289    EPZS16_Terminate_without_Refine:    EPZS16_Terminate_without_Refine:
2290    
2291          *oldMB = *prevMB;          *oldMB = *prevMB;
2292    
2293          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2294          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2295          return iMinSAD;          return iMinSAD;
2296  }  }
2297    
# Line 2233  Line 2306 
2306                          const int y,                          const int y,
2307                          const int start_x,                          const int start_x,
2308                          const int start_y,                          const int start_y,
2309                            const int center_x,
2310                            const int center_y,
2311                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
2312                          const uint32_t iQuant,                          const uint32_t iQuant,
2313                          const uint32_t iFcode,                          const uint32_t iFcode,
# Line 2287  Line 2362 
2362                  max_dy = EVEN(max_dy);                  max_dy = EVEN(max_dy);
2363          }          }
2364          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2365          bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv, psad, 0, 0);          //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv[0].x, pmv[0].y, psad);
2366            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2367    
2368    
2369  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 2322  Line 2398 
2398                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2399                                                  iEdgedWidth), iEdgedWidth);                                                  iEdgedWidth), iEdgedWidth);
2400          iMinSAD +=          iMinSAD +=
2401                  calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2402                                           (uint8_t) iFcode, iQuant);                                           (uint8_t) iFcode, iQuant);
2403    
2404    
# Line 2409  Line 2485 
2485    
2486          iSAD =          iSAD =
2487                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2488                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2489                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2490                                                    iQuant, 0);                                                    iQuant, 0);
2491    
# Line 2425  Line 2501 
2501                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
2502                          iSAD =                          iSAD =
2503                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2504                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2505                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2506                                                                    iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2507    
# Line 2438  Line 2514 
2514                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2515                          iSAD =                          iSAD =
2516                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2517                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2518                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2519                                                                    iQuant, 0);                                                                    iQuant, 0);
2520    
# Line 2455  Line 2531 
2531          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2532                  iMinSAD =                  iMinSAD =
2533                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2534                                                          iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2535                                                          iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2536    
2537    EPZS8_Terminate_without_Refine:    EPZS8_Terminate_without_Refine:
2538    
2539          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2540          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2541          return iMinSAD;          return iMinSAD;
2542  }  }
2543    
2544    
2545    
2546    int32_t
2547    PMVfastIntSearch16(const uint8_t * const pRef,
2548                                    const uint8_t * const pRefH,
2549                                    const uint8_t * const pRefV,
2550                                    const uint8_t * const pRefHV,
2551                                    const IMAGE * const pCur,
2552                                    const int x,
2553                                    const int y,
2554                            const int start_x,
2555                            const int start_y,
2556                            const int center_x,
2557                            const int center_y,
2558                                    const uint32_t MotionFlags,
2559                                    const uint32_t iQuant,
2560                                    const uint32_t iFcode,
2561                                    const MBParam * const pParam,
2562                                    const MACROBLOCK * const pMBs,
2563                                    const MACROBLOCK * const prevMBs,
2564                                    VECTOR * const currMV,
2565                                    VECTOR * const currPMV)
2566    {
2567            const uint32_t iWcount = pParam->mb_width;
2568            const int32_t iWidth = pParam->width;
2569            const int32_t iHeight = pParam->height;
2570            const int32_t iEdgedWidth = pParam->edged_width;
2571    
2572            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2573            const VECTOR zeroMV = { 0, 0 };
2574    
2575            int32_t iDiamondSize;
2576    
2577            int32_t min_dx;
2578            int32_t max_dx;
2579            int32_t min_dy;
2580            int32_t max_dy;
2581    
2582            int32_t iFound;
2583    
2584            VECTOR newMV;
2585            VECTOR backupMV;                        /* just for PMVFAST */
2586    
2587            VECTOR pmv[4];
2588            int32_t psad[4];
2589    
2590            MainSearch16FuncPtr MainSearchPtr;
2591    
2592            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2593            MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2594    
2595            int32_t threshA, threshB;
2596            int32_t bPredEq;
2597            int32_t iMinSAD, iSAD;
2598    
2599    
2600    /* Get maximum range */
2601            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2602                              iFcode);
2603    
2604    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2605    
2606            if ((x == 0) && (y == 0)) {
2607                    threshA = 512;
2608                    threshB = 1024;
2609    
2610                    bPredEq = 0;
2611                    psad[0] = psad[1] = psad[2] = psad[3] = 0;
2612                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2613    
2614            } else {
2615                    threshA = psad[0];
2616                    threshB = threshA + 256;
2617                    if (threshA < 512)
2618                            threshA = 512;
2619                    if (threshA > 1024)
2620                            threshA = 1024;
2621                    if (threshB > 1792)
2622                            threshB = 1792;
2623    
2624                    bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2625                    *currMV = pmv[0];                       /* current best := prediction */
2626            }
2627    
2628            iFound = 0;
2629    
2630    /* Step 4: Calculate SAD around the Median prediction.
2631       MinSAD=SAD
2632       If Motion Vector equal to Previous frame motion vector
2633       and MinSAD<PrevFrmSAD goto Step 10.
2634       If SAD<=256 goto Step 10.
2635    */
2636    
2637            if (currMV->x > max_dx) {
2638                    currMV->x = EVEN(max_dx);
2639            }
2640            if (currMV->x < min_dx) {
2641                    currMV->x = EVEN(min_dx);
2642            }
2643            if (currMV->y > max_dy) {
2644                    currMV->y = EVEN(max_dy);
2645            }
2646            if (currMV->y < min_dy) {
2647                    currMV->y = EVEN(min_dy);
2648            }
2649    
2650            iMinSAD =
2651                    sad16(cur,
2652                              get_iref_mv(pRef, x, y, 16, currMV,
2653                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2654            iMinSAD +=
2655                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2656                                              (uint8_t) iFcode, iQuant);
2657    
2658            if ((iMinSAD < 256) ||
2659                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2660                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2661                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
2662                    {
2663                            if (!MVzero(*currMV)) {
2664                                    iMinSAD += MV16_00_BIAS;
2665                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2666                                    iMinSAD -= MV16_00_BIAS;
2667                            }
2668                    }
2669    
2670                    if (MotionFlags & PMV_EARLYSTOP16)
2671                            goto PMVfastInt16_Terminate_with_Refine;
2672            }
2673    
2674    
2675    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2676       vector of the median.
2677       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2678    */
2679    
2680            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2681                    iFound = 2;
2682    
2683    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2684       Otherwise select large Diamond Search.
2685    */
2686    
2687            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2688                    iDiamondSize = 2;               // halfpel units!
2689            else
2690                    iDiamondSize = 4;               // halfpel units!
2691    
2692    /*
2693       Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2694       Also calculate (0,0) but do not subtract offset.
2695       Let MinSAD be the smallest SAD up to this point.
2696       If MV is (0,0) subtract offset.
2697    */
2698    
2699    // (0,0) is often a good choice
2700    
2701            if (!MVzero(pmv[0]))
2702                    CHECK_MV16_ZERO;
2703    
2704    // previous frame MV is always possible
2705    
2706            if (!MVzero(prevMB->i_mvs[0]))
2707                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2708                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2709    
2710    // left neighbour, if allowed
2711    
2712            if (!MVzero(pmv[1]))
2713                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2714                            if (!MVequal(pmv[1], pmv[0]))
2715                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2716    
2717    // top neighbour, if allowed
2718            if (!MVzero(pmv[2]))
2719                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
2720                            if (!MVequal(pmv[2], pmv[0]))
2721                                    if (!MVequal(pmv[2], pmv[1]))
2722                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2723    
2724    // top right neighbour, if allowed
2725                                            if (!MVzero(pmv[3]))
2726                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
2727                                                            if (!MVequal(pmv[3], pmv[0]))
2728                                                                    if (!MVequal(pmv[3], pmv[1]))
2729                                                                            if (!MVequal(pmv[3], pmv[2]))
2730                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
2731                                                                                                                             pmv[3].y);
2732    
2733            if ((MVzero(*currMV)) &&
2734                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2735                    iMinSAD -= MV16_00_BIAS;
2736    
2737    
2738    /* Step 6: If MinSAD <= thresa goto Step 10.
2739       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2740    */
2741    
2742            if ((iMinSAD <= threshA) ||
2743                    (MVequal(*currMV, prevMB->i_mvs[0]) &&
2744                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2745    
2746                    if (MotionFlags & PMV_EARLYSTOP16)
2747                            goto PMVfastInt16_Terminate_with_Refine;
2748            }
2749    
2750    
2751    /************ (Diamond Search)  **************/
2752    /*
2753       Step 7: Perform Diamond search, with either the small or large diamond.
2754       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
2755       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
2756       If center then goto step 10.
2757       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
2758       Refine by using small diamond and goto step 10.
2759    */
2760    
2761            if (MotionFlags & PMV_USESQUARES16)
2762                    MainSearchPtr = Square16_MainSearch;
2763            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2764                    MainSearchPtr = AdvDiamond16_MainSearch;
2765            else
2766                    MainSearchPtr = Diamond16_MainSearch;
2767    
2768            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2769    
2770    
2771    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2772            iSAD =
2773                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2774                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2775                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2776                                                      iQuant, iFound);
2777    
2778            if (iSAD < iMinSAD) {
2779                    *currMV = newMV;
2780                    iMinSAD = iSAD;
2781            }
2782    
2783            if (MotionFlags & PMV_EXTSEARCH16) {
2784    /* extended: search (up to) two more times: orignal prediction and (0,0) */
2785    
2786                    if (!(MVequal(pmv[0], backupMV))) {
2787                            iSAD =
2788                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2789                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2790                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2791                                                                      iDiamondSize, iFcode, iQuant, iFound);
2792    
2793                            if (iSAD < iMinSAD) {
2794                                    *currMV = newMV;
2795                                    iMinSAD = iSAD;
2796                            }
2797                    }
2798    
2799                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2800                            iSAD =
2801                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2802                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2803                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
2804                                                                      iQuant, iFound);
2805    
2806                            if (iSAD < iMinSAD) {
2807                                    *currMV = newMV;
2808                                    iMinSAD = iSAD;
2809                            }
2810                    }
2811            }
2812    
2813    /*
2814       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
2815    */
2816    
2817    PMVfastInt16_Terminate_with_Refine:
2818    
2819            pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
2820            pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
2821    
2822            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2823                    iMinSAD =
2824                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2825                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2826                                                             iFcode, iQuant, iEdgedWidth);
2827    
2828            pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
2829    
2830    PMVfastInt16_Terminate_without_Refine:
2831            currPMV->x = currMV->x - center_x;
2832            currPMV->y = currMV->y - center_y;
2833            return iMinSAD;
2834    }
2835    
2836    
2837    
2838  /* ***********************************************************  /* ***********************************************************
# Line 2475  Line 2841 
2841  ***************************************************************/  ***************************************************************/
2842    
2843    
2844    #define DIRECT_PENALTY 0
2845    #define DIRECT_UPPERLIMIT 256   // never use direct mode if SAD is larger than this
2846    
2847  void  void
2848  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
2849                                           FRAMEINFO * const frame,                                           FRAMEINFO * const frame,
2850                                             const int32_t time_bp,
2851                                             const int32_t time_pp,
2852                                           // forward (past) reference                                           // forward (past) reference
2853                                           const MACROBLOCK * const f_mbs,                                           const MACROBLOCK * const f_mbs,
2854                                           const IMAGE * const f_ref,                                           const IMAGE * const f_ref,
# Line 2491  Line 2862 
2862                                           const IMAGE * const b_refV,                                           const IMAGE * const b_refV,
2863                                           const IMAGE * const b_refHV)                                           const IMAGE * const b_refHV)
2864  {  {
2865          const uint32_t mb_width = pParam->mb_width;          const int mb_width = pParam->mb_width;
2866          const uint32_t mb_height = pParam->mb_height;          const int mb_height = pParam->mb_height;
2867          const int32_t edged_width = pParam->edged_width;          const int edged_width = pParam->edged_width;
2868    
2869          uint32_t i, j;          int i, j, k;
2870    
2871          int32_t f_sad16;          static const VECTOR zeroMV={0,0};
2872          int32_t b_sad16;  
2873          int32_t i_sad16;          int f_sad16;    /* forward (as usual) search */
2874          int32_t d_sad16;          int b_sad16;    /* backward (only in b-frames) search */
2875          int32_t best_sad;          int i_sad16;    /* interpolated (both direction, b-frames only) */
2876            int d_sad16;    /* direct mode (assume linear motion) */
2877    
2878            int best_sad;
2879    
2880            VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
2881          VECTOR pmv_dontcare;          VECTOR pmv_dontcare;
2882    
2883            int f_count=0;
2884            int b_count=0;
2885            int i_count=0;
2886            int d_count=0;
2887            int s_count=0;
2888    
2889            const int64_t TRB = (int32_t)time_pp - (int32_t)time_bp;
2890        const int64_t TRD = (int32_t)time_pp;
2891    
2892            // fprintf(stderr,"TRB = %lld  TRD = %lld  time_bp =%d time_pp =%d\n\n",TRB,TRD,time_bp,time_pp);
2893          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
2894          for (j = 0; j < mb_height; j++) {          for (j = 0; j < mb_height; j++) {
2895    
2896                    f_predMV = zeroMV;      /* prediction is reset at left boundary */
2897                    b_predMV = zeroMV;
2898    
2899                  for (i = 0; i < mb_width; i++) {                  for (i = 0; i < mb_width; i++) {
2900                          MACROBLOCK *mb = &frame->mbs[i + j * mb_width];                          MACROBLOCK *mb = &frame->mbs[i + j * mb_width];
2901                          const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width];                          const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width];
2902                          const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width];                          const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width];
2903    
2904                            mb->deltamv=zeroMV;
2905    
2906    /* special case, if collocated block is SKIPed: encoding is forward(0,0)  */
2907    
2908    #ifndef _DISABLE_SKIP
2909                          if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&                          if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
2910                                  b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {                                  b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {
2911                                  mb->mode = MODE_NOT_CODED;                                  mb->mode = MODE_NOT_CODED;
# Line 2521  Line 2915 
2915                                  mb->b_mvs[0].y = 0;                                  mb->b_mvs[0].y = 0;
2916                                  continue;                                  continue;
2917                          }                          }
2918                  /* force F_SAD16  #endif
                         f_sad16 = 100;  
                         b_sad16 = 65535;  
2919    
2920                          mb->mode = MODE_FORWARD;                          d_sad16 = DIRECT_PENALTY;
                         mb->mvs[0].x = 1;  
                         mb->mvs[0].y = 1;  
                         mb->b_mvs[0].x = 1;  
                         mb->b_mvs[0].y = 1;  
                         continue;  
                  ^^ force F_SAD16 */  
2921    
2922                            if (b_mb->mode == MODE_INTER4V)
2923                            {
2924    
2925                            /* same method of scaling as in decoder.c, so we copy from there */
2926                        for (k = 0; k < 4; k++) {
2927    
2928                                            mb->directmv[k] = b_mb->mvs[k];
2929    
2930                                            mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
2931                        mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
2932                                                                                    ? ((TRB - TRD) * mb->directmv[k].x) / TRD
2933                                                : mb->mvs[k].x - mb->directmv[k].x);
2934    
2935                        mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
2936                            mb->b_mvs[k].y = (int32_t) ((mb->directmv[k].y == 0)
2937                                                                                    ? ((TRB - TRD) * mb->directmv[k].y) / TRD
2938                                                : mb->mvs[k].y - mb->directmv[k].y);
2939    
2940                                            d_sad16 +=
2941                                                    sad8bi(frame->image.y + 2*(i+(k&1))*8 + 2*(j+(k>>1))*8*edged_width,
2942                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2943                                                                    2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->mvs[k], edged_width),
2944                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2945                                                                    2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->b_mvs[k], edged_width),
2946                                                      edged_width);
2947                                    }
2948                            }
2949                            else
2950                            {
2951                                    mb->directmv[3] = mb->directmv[2] = mb->directmv[1] =
2952                                    mb->directmv[0] = b_mb->mvs[0];
2953    
2954                                    mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
2955                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
2956                                                                            ? ((TRB - TRD) * mb->directmv[0].x) / TRD
2957                                        : mb->mvs[0].x - mb->directmv[0].x);
2958    
2959                        mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
2960                    mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
2961                                                                            ? ((TRB - TRD) * mb->directmv[0].y) / TRD
2962                                        : mb->mvs[0].y - mb->directmv[0].y);
2963    
2964                                    d_sad16 += sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
2965                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2966                                                                    i, j, 16, &mb->mvs[0], edged_width),
2967                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2968                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
2969                                                      edged_width);
2970    
2971                }
2972                        d_sad16 += calc_delta_16(mb->deltamv.x, mb->deltamv.y, 1, frame->quant);
2973    
2974                          // forward search                          // forward search
2975                          f_sad16 =                          f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2976                                  SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                                  &frame->image, i, j,
2977                                                   &frame->image, i, j, frame->motion_flags,                                                  mb->mvs[0].x, mb->mvs[0].y,                     /* start point f_directMV */
2978                                                    f_predMV.x, f_predMV.y,                         /* center is f-prediction */
2979                                                    frame->motion_flags,
2980                                                   frame->quant, frame->fcode, pParam,                                                   frame->quant, frame->fcode, pParam,
2981                                                   f_mbs,  f_mbs, /* todo */                                                  f_mbs, f_mbs,
2982                                                   &mb->mvs[0], &pmv_dontcare);   // ignore pmv                                                  &mb->mvs[0], &pmv_dontcare);
2983    
2984    
2985                          // backward search                          // backward search
2986                          b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                          b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2987                                                  &frame->image, i, j, frame->motion_flags,                                                  &frame->image, i, j,
2988                                                    mb->b_mvs[0].x, mb->b_mvs[0].y,         /* start point b_directMV */
2989                                                    b_predMV.x, b_predMV.y,                         /* center is b-prediction */
2990                                                    frame->motion_flags,
2991                                                  frame->quant, frame->bcode, pParam,                                                  frame->quant, frame->bcode, pParam,
2992                                                  b_mbs, b_mbs,   /* todo */                                                  b_mbs, b_mbs,
2993                                                  &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv                                                  &mb->b_mvs[0], &pmv_dontcare);
   
                         // interpolate search (simple, but effective)  
                         i_sad16 = 65535;  
2994    
                         /*  
                         x/y range somewhat buggy  
2995                          i_sad16 =                          i_sad16 =
2996                                  sad16bi_c(frame->image.y + i * 16 + j * 16 * edged_width,                                  sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
2997                                                    get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                                    get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2998                                                                    i, j, 16, mb->mvs[0].x, mb->mvs[0].y,                                                                  i, j, 16, &mb->mvs[0], edged_width),
2999                                                                    edged_width), get_ref(b_ref->y, b_refH->y,                                                    get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3000                                                                                                                  b_refV->y, b_refHV->y,                                                                  i, j, 16, &mb->b_mvs[0], edged_width),
                                                                                                                 i, j, 16,  
                                                                                                                 mb->b_mvs[0].x,  
                                                                                                                 mb->b_mvs[0].x,  
                                                                                                                 edged_width),  
3001                                                    edged_width);                                                    edged_width);
3002                          */                      i_sad16 += calc_delta_16(mb->mvs[0].x-f_predMV.x, mb->mvs[0].y-f_predMV.y,
3003                                                                    frame->fcode, frame->quant);
3004                        i_sad16 += calc_delta_16(mb->b_mvs[0].x-b_predMV.x, mb->b_mvs[0].y-b_predMV.y,
3005                                                                    frame->bcode, frame->quant);
3006    
3007                          // TODO: direct search                          // TODO: direct search
3008                          // predictor + range of [-32,32]                          // predictor + delta vector in range [-32,32] (fcode=1)
                         d_sad16 = 65535;  
3009    
3010                            i_sad16 = 65535;
3011                            f_sad16 = 65535;
3012                            b_sad16 = 65535;
3013    //                      d_sad16 = 65535;
3014    
3015                          if (f_sad16 < b_sad16) {                          if (f_sad16 < b_sad16) {
3016                                  best_sad = f_sad16;                                  best_sad = f_sad16;
# Line 2586  Line 3026 
3026                          }                          }
3027    
3028                          if (d_sad16 < best_sad) {                          if (d_sad16 < best_sad) {
3029    
3030                                    if (b_mb->mode == MODE_INTER4V)
3031                                    {
3032    
3033                                    /* same method of scaling as in decoder.c, so we copy from there */
3034                                for (k = 0; k < 4; k++) {
3035    
3036                                                    mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3037                                mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3038                                                                                            ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3039                                                        : mb->mvs[k].x - mb->directmv[k].x);
3040    
3041                                mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3042                            mb->b_mvs[k].y = (int32_t) ((mb->directmv[k].y == 0)
3043                                                                                            ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3044                                                : mb->mvs[k].y - mb->directmv[k].y);
3045                                            }
3046                                    }
3047                                    else
3048                                    {
3049                                            mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3050    
3051                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3052                                                                                    ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3053                                            : mb->mvs[0].x - mb->directmv[0].x);
3054    
3055                                mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3056    
3057                            mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
3058                                                                                    ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3059                                                : mb->mvs[0].y - mb->directmv[0].y);
3060    
3061                                            mb->mvs[3] = mb->mvs[2] = mb->mvs[1] = mb->mvs[0];
3062                                            mb->b_mvs[3] = mb->b_mvs[2] = mb->b_mvs[1] = mb->b_mvs[0];
3063                    }
3064    
3065                                  best_sad = d_sad16;                                  best_sad = d_sad16;
3066                                  mb->mode = MODE_DIRECT;                                  mb->mode = MODE_DIRECT;
3067                                    mb->mode = MODE_INTERPOLATE;            // direct mode still broken :-(
3068                            }
3069    
3070                            switch (mb->mode)
3071                            {
3072                                    case MODE_FORWARD:
3073                                            f_count++;
3074                                            f_predMV = mb->mvs[0];
3075                                            break;
3076                                    case MODE_BACKWARD:
3077                                            b_count++;
3078                                            b_predMV = mb->b_mvs[0];
3079    
3080                                            break;
3081                                    case MODE_INTERPOLATE:
3082                                            i_count++;
3083                                            f_predMV = mb->mvs[0];
3084                                            b_predMV = mb->b_mvs[0];
3085                                            break;
3086                                    case MODE_DIRECT:
3087                                            d_count++;
3088                                            break;
3089                                    default:
3090                                            s_count++;              // ???
3091                                            break;
3092                          }                          }
3093    
3094                  }                  }
3095          }          }
3096    
3097    #ifdef _DEBUG_BFRAME_STAT
3098            fprintf(stderr,"B-Stat: F: %04d   B: %04d   I: %04d  D: %04d   S: %04d\n",
3099                                    f_count,b_count,i_count,d_count,s_count);
3100    #endif
3101    
3102  }  }

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

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