[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 118, Sat Apr 13 16:30:02 2002 UTC revision 348, Sun Jul 28 17:10:39 2002 UTC
# Line 1  Line 1 
1  /**************************************************************************  /**************************************************************************
2   *   *
3     *      XVID MPEG-4 VIDEO CODEC
4     *      motion estimation
5     *
6     *      This program is an implementation of a part of one or more MPEG-4
7     *      Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
8     *      to use this software module in hardware or software products are
9     *      advised that its use may infringe existing patents or copyrights, and
10     *      any such use would be at such party's own risk.  The original
11     *      developer of this software module and his/her company, and subsequent
12     *      editors and their companies, will have no liability for use of this
13     *      software or modifications or derivatives thereof.
14     *
15     *      This program is free software; you can redistribute it and/or modify
16     *      it under the terms of the GNU General Public License as published by
17     *      the Free Software Foundation; either version 2 of the License, or
18     *      (at your option) any later version.
19     *
20     *      This program is distributed in the hope that it will be useful,
21     *      but WITHOUT ANY WARRANTY; without even the implied warranty of
22     *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     *      GNU General Public License for more details.
24     *
25     *      You should have received a copy of the GNU General Public License
26     *      along with this program; if not, write to the Free Software
27     *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28     *
29     *************************************************************************/
30    
31    /**************************************************************************
32     *
33   *  Modifications:   *  Modifications:
34   *   *
35     *      01.05.2002      updated MotionEstimationBVOP
36     *      25.04.2002 partial prevMB conversion
37     *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>
38   *      14.04.2002 added MotionEstimationBVOP()   *      14.04.2002 added MotionEstimationBVOP()
39   *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between   *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between
40   *             EPZS and EPZS^2   *             EPZS and EPZS^2
# Line 44  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  
   
 /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  
 /* nb  = vop pixels * 2^(bpp-8) */  
 #define MV16_00_BIAS    (128+1)  
   
 /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */  
 #define INTER_BIAS      512  
   
 /* Parameters which control inter/inter4v decision */  
 #define IMV16X16                        5  
   
 /* vector map (vlc delta size) smoother parameters */  
 #define NEIGH_TEND_16X16        2  
 #define NEIGH_TEND_8X8          2  
   
   
 // fast ((A)/2)*2  
 #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  
   
   
 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 MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         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 MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         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, int start_y,  
                                         const uint32_t MotionFlags,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         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, int start_y,  
                                         const uint32_t MotionFlags,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
80    
 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);  
81    
82  typedef MainSearch16Func* MainSearch16FuncPtr;  static int32_t lambda_vec16[32] =       /* rounded values for lambda param for weight of motion bits as in modified H.26L */
83    { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),
84                    (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),
85            (int) (1.89187 + 0.5), (int) (2.11542 + 0.5), (int) (2.35878 + 0.5),
86                    (int) (2.62429 + 0.5), (int) (2.91455 + 0.5),
87            (int) (3.23253 + 0.5), (int) (3.58158 + 0.5), (int) (3.96555 + 0.5),
88                    (int) (4.38887 + 0.5), (int) (4.85673 + 0.5),
89            (int) (5.37519 + 0.5), (int) (5.95144 + 0.5), (int) (6.59408 + 0.5),
90                    (int) (7.31349 + 0.5), (int) (8.12242 + 0.5),
91            (int) (9.03669 + 0.5), (int) (10.0763 + 0.5), (int) (11.2669 + 0.5),
92                    (int) (12.6426 + 0.5), (int) (14.2493 + 0.5),
93            (int) (16.1512 + 0.5), (int) (18.442 + 0.5), (int) (21.2656 + 0.5),
94                    (int) (24.8580 + 0.5), (int) (29.6436 + 0.5),
95            (int) (36.4949 + 0.5)
96    };
97    
98    static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now */
99    
 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);  
100    
 typedef MainSearch8Func* MainSearch8FuncPtr;  
101    
102  // mv.length table  // mv.length table
103  static const uint32_t mvtab[33] = {  static const uint32_t mvtab[33] = {
# Line 178  Line 108 
108  };  };
109    
110    
111  static __inline uint32_t mv_bits(int32_t component, const uint32_t iFcode)  static __inline uint32_t
112    mv_bits(int32_t component,
113                    const uint32_t iFcode)
114  {  {
115      if (component == 0)      if (component == 0)
116                  return 1;                  return 1;
# Line 186  Line 118 
118      if (component < 0)      if (component < 0)
119                  component = -component;                  component = -component;
120    
121      if (iFcode == 1)          if (iFcode == 1) {
     {  
122                  if (component > 32)                  if (component > 32)
123                      component = 32;                      component = 32;
124    
# Line 204  Line 135 
135  }  }
136    
137    
138  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode)  static __inline uint32_t
139  {  calc_delta_16(const int32_t dx,
140          return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));                            const int32_t dy,
141  }                            const uint32_t iFcode,
142                              const uint32_t iQuant)
143  static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)  {
144            return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) +
145  {                                                                                                            mv_bits(dy, iFcode));
146      return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));  }
147  }  
148    static __inline uint32_t
149    calc_delta_8(const int32_t dx,
150                             const int32_t dy,
151                             const uint32_t iFcode,
152                             const uint32_t iQuant)
153  #ifndef SEARCH16  {
154  #define SEARCH16        PMVfastSearch16          return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) +
155  //#define SEARCH16      FullSearch16                                                                                                     mv_bits(dy, iFcode));
156  //#define SEARCH16      EPZSSearch16  }
157  #endif  
158    bool
159  #ifndef SEARCH8  MotionEstimation(MBParam * const pParam,
160  #define SEARCH8         PMVfastSearch8                                   FRAMEINFO * const current,
161  //#define SEARCH8       EPZSSearch8                                   FRAMEINFO * const reference,
 #endif  
   
 bool MotionEstimation(  
         MACROBLOCK * const pMBs,  
         MBParam * const pParam,  
         const IMAGE * const pRef,  
162          const IMAGE * const pRefH,          const IMAGE * const pRefH,
163          const IMAGE * const pRefV,          const IMAGE * const pRefV,
164          const IMAGE * const pRefHV,          const IMAGE * const pRefHV,
         IMAGE * const pCurrent,  
165          const uint32_t iLimit)          const uint32_t iLimit)
   
166  {  {
167          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
168          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
169            MACROBLOCK *const pMBs = current->mbs;
170          uint32_t i, j, iIntra = 0;          MACROBLOCK *const prevMBs = reference->mbs;
171            const IMAGE *const pCurrent = &current->image;
172          VECTOR mv16;          const IMAGE *const pRef = &reference->image;
173          VECTOR pmv16;  
174            static const VECTOR zeroMV = { 0, 0 };
175          int32_t sad8 = 0;          VECTOR predMV;
176          int32_t sad16;  
177          int32_t deviation;          int32_t x, y;
178            int32_t iIntra = 0;
179            VECTOR pmv;
180    
181          if (sadInit)          if (sadInit)
182                  (*sadInit)();                  (*sadInit)();
183    
184          // note: i==horizontal, j==vertical          for (y = 0; y < iHcount; y++)   {
185          for (i = 0; i < iHcount; i++)                  for (x = 0; x < iWcount; x ++)  {
                 for (j = 0; j < iWcount; j++)  
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
186    
187                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
                                          j, i, pParam->motion_flags,  
                                          pParam, pMBs, &mv16, &pmv16);  
                         pMB->sad16=sad16;  
188    
189                            predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
190    
191                          /* decide: MODE_INTER or MODE_INTRA                          pMB->sad16 =
192                             if (dev_intra < sad_inter - 2 * nb) use_intra                                  SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
193                          */                                                   x, y, predMV.x, predMV.y, predMV.x, predMV.y,
194                                                     current->motion_flags, current->quant,
195                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
196                                                     &pMB->pmvs[0]);
197    
198                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                          if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
199                                    int32_t deviation;
200    
201                          if (deviation < (sad16 - INTER_BIAS))                                  deviation =
202                          {                                          dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
203                                                      pParam->edged_width);
204    
205                                    if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
206                                  pMB->mode = MODE_INTRA;                                  pMB->mode = MODE_INTRA;
207                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
208                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                                  pMB->mvs[3] = zeroMV;
209                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
210                                                    pMB->sad8[3] = 0;
211    
212                                  iIntra++;                                  iIntra++;
213                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 286  Line 215 
215    
216                                  continue;                                  continue;
217                          }                          }
   
                         if (pParam->global_flags & XVID_INTER4V)  
                         {  
                                 pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j, 2 * i, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[0], &pMB->pmvs[0]);  
   
                                 pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j + 1, 2 * i, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[1], &pMB->pmvs[1]);  
   
                                 pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[2], &pMB->pmvs[2]);  
   
                                 pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j + 1, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[3], &pMB->pmvs[3]);  
   
                                 sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];  
218                          }                          }
219    
220                            pmv = pMB->pmvs[0];
221                            if (current->global_flags & XVID_INTER4V)
222                                    if ((!(current->global_flags & XVID_LUMIMASKING) ||
223                                             pMB->dquant == NO_CHANGE)) {
224                                            int32_t sad8 = IMV16X16 * current->quant;
225    
226                                            if (sad8 < pMB->sad16) {
227                                                    sad8 += pMB->sad8[0] =
228                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
229                                                                            pCurrent, 2 * x, 2 * y,
230                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
231                                                                            current->motion_flags,
232                                                                            current->quant, current->fcode, pParam,
233                                                                            pMBs, prevMBs, &pMB->mvs[0],
234                                                                            &pMB->pmvs[0]);
235                                            }
236                                            if (sad8 < pMB->sad16) {
237    
238                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
239                                                    sad8 += pMB->sad8[1] =
240                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
241                                                                            pCurrent, 2 * x + 1, 2 * y,
242                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
243                                                                            current->motion_flags,
244                                                                            current->quant, current->fcode, pParam,
245                                                                            pMBs, prevMBs, &pMB->mvs[1],
246                                                                            &pMB->pmvs[1]);
247                                            }
248                                            if (sad8 < pMB->sad16) {
249                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
250                                                    sad8 += pMB->sad8[2] =
251                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
252                                                                            pCurrent, 2 * x, 2 * y + 1,
253                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
254                                                                            current->motion_flags,
255                                                                            current->quant, current->fcode, pParam,
256                                                                            pMBs, prevMBs, &pMB->mvs[2],
257                                                                            &pMB->pmvs[2]);
258                                            }
259                                            if (sad8 < pMB->sad16) {
260                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
261                                                    sad8 += pMB->sad8[3] =
262                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
263                                                                            pCurrent, 2 * x + 1, 2 * y + 1,
264                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
265                                                                            current->motion_flags,
266                                                                            current->quant, current->fcode, pParam,
267                                                                            pMBs, prevMBs,
268                                                                            &pMB->mvs[3],
269                                                                            &pMB->pmvs[3]);
270                                            }
271    
272                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
273                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
274                          */                          */
275    
276                          if (pMB->dquant == NO_CHANGE) {                                          if (sad8 < pMB->sad16) {
                                 if (((pParam->global_flags & XVID_INTER4V)==0) ||  
                                     (sad16 < (sad8 + (int32_t)(IMV16X16 * pParam->quant)))) {  
   
                                         sad8 = sad16;  
                                         pMB->mode = MODE_INTER;  
                                         pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;  
                                         pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;  
                                         pMB->pmvs[0].x = pmv16.x;  
                                         pMB->pmvs[0].y = pmv16.y;  
                                 }  
                                 else  
277                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
278                                                    pMB->sad8[0] *= 4;
279                                                    pMB->sad8[1] *= 4;
280                                                    pMB->sad8[2] *= 4;
281                                                    pMB->sad8[3] *= 4;
282                                                    continue;
283                          }                          }
284                          else  
285                          {                                  }
286                                  sad8 = sad16;  
287                                  pMB->mode = MODE_INTER;                                  pMB->mode = MODE_INTER;
288                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;                          pMB->pmvs[0] = pmv;     /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
289                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
290                                  pMB->pmvs[0].x = pmv16.x;                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
291                                  pMB->pmvs[0].y = pmv16.y;                                  pMB->sad16;
292                          }                          }
293                  }                  }
294    
295          return 0;          return 0;
296  }  }
297    
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
   
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
298    
299  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
300    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
301      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
302    { \    { \
303      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \
304      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
     if (iSAD <= iQuant * 96)    \  
         iSAD -= MV16_00_BIAS; \  
305      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
306      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
307  }  }
308    
309  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #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 370  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 380  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 390  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 398  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 406  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 416  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 426  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 436  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 451  Line 399 
399                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
400                                          const int x, const int y,                                          const int x, const int y,
401                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
402                                            const uint32_t iQuant,
403                                            const uint32_t iFcode,
404                                          MBParam * const pParam,                                          MBParam * const pParam,
405                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
406                                            const MACROBLOCK * const prevMBs,
407                                          VECTOR * const currMV,                                          VECTOR * const currMV,
408                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
409  {  {
410          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
411          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
412          int32_t iSAD;          int32_t iSAD;
413          int32_t pred_x,pred_y;          VECTOR pred;
414    
415          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);  
416            pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
417    
418          iSAD = sad16( cur,          iSAD = sad16( cur,
419                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
# Line 472  Line 423 
423    
424          currMV->x = 0;          currMV->x = 0;
425          currMV->y = 0;          currMV->y = 0;
426          currPMV->x = -pred_x;          currPMV->x = -pred.x;
427          currPMV->y = -pred_y;          currPMV->y = -pred.y;
428    
429          return iSAD;          return iSAD;
430    
431  }  }
432  */  */
433    
434  int32_t Diamond16_MainSearch(  int32_t
435          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
436          const uint8_t * const pRefH,          const uint8_t * const pRefH,
437          const uint8_t * const pRefV,          const uint8_t * const pRefV,
438          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
439          const uint8_t * const cur,          const uint8_t * const cur,
440          const int x, const int y,                                           const int x,
441          int32_t startx, int32_t starty,                                           const int y,
442          int32_t iMinSAD,                                     const int start_x,
443                                       const int start_y,
444                                       int iMinSAD,
445          VECTOR * const currMV,          VECTOR * const currMV,
446          const VECTOR * const pmv,                                     const int center_x,
447          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
448          const int32_t min_dy, const int32_t max_dy,                                           const int32_t min_dx,
449                                             const int32_t max_dx,
450                                             const int32_t min_dy,
451                                             const int32_t max_dy,
452          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
453          const int32_t iDiamondSize,          const int32_t iDiamondSize,
454          const int32_t iFcode,          const int32_t iFcode,
# Line 502  Line 458 
458  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
459    
460          int32_t iDirection=0;          int32_t iDirection=0;
461            int32_t iDirectionBackup;
462          int32_t iSAD;          int32_t iSAD;
463          VECTOR backupMV;          VECTOR backupMV;
464          backupMV.x = startx;  
465          backupMV.y = starty;          backupMV.x = start_x;
466            backupMV.y = start_y;
467    
468  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
469    
# Line 514  Line 472 
472          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
473          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
474    
475          if (iDirection)          if (iDirection) {
476                  while (!iFound)                  while (!iFound) {
                 {  
477                          iFound = 1;                          iFound = 1;
478                          backupMV=*currMV;                          backupMV=*currMV;
479                            iDirectionBackup = iDirection;
480    
481                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
482                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
483                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
484                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
485                          if ( iDirection != 4)                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
486                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                     backupMV.y, 2);
487                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
488                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
489                                                                                       backupMV.y - iDiamondSize, 3);
490                            if (iDirectionBackup != 3)
491                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
492                                                                                       backupMV.y + iDiamondSize, 4);
493                  }                  }
494          else          } else {
495          {                  currMV->x = start_x;
496                  currMV->x = startx;                  currMV->y = start_y;
                 currMV->y = starty;  
497          }          }
498          return iMinSAD;          return iMinSAD;
499  }  }
500    
501  int32_t Square16_MainSearch(  int32_t
502                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
503                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
504                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
505                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
506                                          const uint8_t * const cur,                                          const uint8_t * const cur,
507                                          const int x, const int y,                                          const int x,
508                                          int32_t startx, int32_t starty,                                          const int y,
509                                          int32_t iMinSAD,                                     const int start_x,
510                                       const int start_y,
511                                       int iMinSAD,
512                                          VECTOR * const currMV,                                          VECTOR * const currMV,
513                                          const VECTOR * const pmv,                                     const int center_x,
514                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
515                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
516                                            const int32_t max_dx,
517                                            const int32_t min_dy,
518                                            const int32_t max_dy,
519                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
520                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
521                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 561  Line 527 
527          int32_t iDirection=0;          int32_t iDirection=0;
528          int32_t iSAD;          int32_t iSAD;
529          VECTOR backupMV;          VECTOR backupMV;
530          backupMV.x = startx;  
531          backupMV.y = starty;          backupMV.x = start_x;
532            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 577  Line 544 
544          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
545          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
546    
547          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
548          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
549          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
550          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
551            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
552                                                             backupMV.y - iDiamondSize, 7);
553            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
554                                                             backupMV.y + iDiamondSize, 8);
555    
556    
557          if (iDirection)          if (iDirection) {
558                  while (!iFound)                  while (!iFound) {
                 {  
559                          iFound = 1;                          iFound = 1;
560                          backupMV=*currMV;                          backupMV=*currMV;
561    
562                          switch (iDirection)                          switch (iDirection) {
                         {  
563                                  case 1:                                  case 1:
564                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
565                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
566                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
567                                                                                     backupMV.y - iDiamondSize, 5);
568                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
569                                                                                     backupMV.y - iDiamondSize, 7);
570                                          break;                                          break;
571                                  case 2:                                  case 2:
572                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
573                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
574                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
575                                                                                     backupMV.y + iDiamondSize, 6);
576                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
577                                                                                     backupMV.y + iDiamondSize, 8);
578                                          break;                                          break;
579    
580                                  case 3:                                  case 3:
581                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
582                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
583                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
584                                                                                     backupMV.y - iDiamondSize, 7);
585                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
586                                                                                     backupMV.y + iDiamondSize, 8);
587                                          break;                                          break;
588    
589                                  case 4:                                  case 4:
590                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
591                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
592                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
593                                                                                     backupMV.y - iDiamondSize, 5);
594                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
595                                                                                     backupMV.y + iDiamondSize, 6);
596                                          break;                                          break;
597    
598                                  case 5:                                  case 5:
599                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
600                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
601                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
602                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
603                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
604                                                                                     backupMV.y - iDiamondSize, 5);
605                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
606                                                                                     backupMV.y + iDiamondSize, 6);
607                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
608                                                                                     backupMV.y - iDiamondSize, 7);
609                                          break;                                          break;
610    
611                                  case 6:                                  case 6:
612                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
613                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
614                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
615                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
616                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
617                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
618                                                                                     backupMV.y - iDiamondSize, 5);
619                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
620                                                                                     backupMV.y + iDiamondSize, 6);
621                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
622                                                                                     backupMV.y + iDiamondSize, 8);
623    
624                                          break;                                          break;
625    
626                                  case 7:                                  case 7:
627                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
628                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
629                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
630                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
631                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
632                                                                                     backupMV.y - iDiamondSize, 5);
633                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
634                                                                                     backupMV.y - iDiamondSize, 7);
635                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
636                                                                                     backupMV.y + iDiamondSize, 8);
637                                          break;                                          break;
638    
639                                  case 8:                                  case 8:
640                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
641                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
642                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
643                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
644                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
645                                                                                     backupMV.y + iDiamondSize, 6);
646                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
647                                                                                     backupMV.y - iDiamondSize, 7);
648                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
649                                                                                     backupMV.y + iDiamondSize, 8);
650                                          break;                                          break;
651                          default:                          default:
652                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
653                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
654                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
655                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
656                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
657                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
658                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
659                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
660                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
661                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
662                                                                                     backupMV.y - iDiamondSize, 5);
663                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
664                                                                                     backupMV.y + iDiamondSize, 6);
665                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
666                                                                                     backupMV.y - iDiamondSize, 7);
667                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
668                                                                                     backupMV.y + iDiamondSize, 8);
669                                          break;                                          break;
670                          }                          }
671                  }                  }
672          else          } else {
673                  {                  currMV->x = start_x;
674                          currMV->x = startx;                  currMV->y = start_y;
                         currMV->y = starty;  
675                  }                  }
676          return iMinSAD;          return iMinSAD;
677  }  }
678    
679    
680  int32_t Full16_MainSearch(  int32_t
681                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
682                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
683                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
684                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
685                                          const uint8_t * const cur,                                          const uint8_t * const cur,
686                                          const int x, const int y,                                    const int x,
687                                          int32_t startx, int32_t starty,                                    const int y,
688                                          int32_t iMinSAD,                                     const int start_x,
689                                       const int start_y,
690                                       int iMinSAD,
691                                          VECTOR * const currMV,                                          VECTOR * const currMV,
692                                          const VECTOR * const pmv,                                     const int center_x,
693                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
694                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
695                                      const int32_t max_dx,
696                                      const int32_t min_dy,
697                                      const int32_t max_dy,
698                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
699                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
700                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 691  Line 704 
704          int32_t iSAD;          int32_t iSAD;
705          int32_t dx,dy;          int32_t dx,dy;
706          VECTOR backupMV;          VECTOR backupMV;
707          backupMV.x = startx;  
708          backupMV.y = starty;          backupMV.x = start_x;
709            backupMV.y = start_y;
710    
711          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
712                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 701  Line 715 
715          return iMinSAD;          return iMinSAD;
716  }  }
717    
718  int32_t Full8_MainSearch(  int32_t
719                                          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
720                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
721                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
722                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
723                                          const uint8_t * const cur,                                          const uint8_t * const cur,
724                                          const int x, const int y,                                                  const int x,
725                                          int32_t startx, int32_t starty,                                                  const int y,
726                                          int32_t iMinSAD,                                             int start_x,
727                                               int start_y,
728                                               int iMinSAD,
729                                          VECTOR * const currMV,                                          VECTOR * const currMV,
730                                          const VECTOR * const pmv,                                             const int center_x,
731                                          const int32_t min_dx, const int32_t max_dx,                                             const int center_y,
732                                          const int32_t min_dy, const int32_t max_dy,                                                  const int32_t min_dx,
733                                                    const int32_t max_dx,
734                                                    const int32_t min_dy,
735                                                    const int32_t max_dy,
736                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
737                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
738                                          const int32_t iFcode,                                          const int32_t iFcode,
739                                          const int32_t iQuant,                                          const int32_t iQuant,
740                                          int iFound)                                                  int iDirection)
741  {  {
742    
743          int32_t iSAD;          int32_t iSAD;
         int32_t dx,dy;  
         VECTOR backupMV;  
         backupMV.x = startx;  
         backupMV.y = starty;  
744    
745          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
                 for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)  
                         NOCHECK_MV8_CANDIDATE(dx,dy);  
746    
747          return iMinSAD;          if (iDirection) {
748  }                  CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
749                    CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
750                    CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
751                    CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
752            } else {
753                    int bDirection = 1 + 2 + 4 + 8;
754    
755                    do {
756                            iDirection = 0;
757                            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)
758                                    CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
759    
760                            if (bDirection & 2)
761                                    CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
762    
763  int32_t Halfpel16_Refine(                          if (bDirection & 4)
764          const uint8_t * const pRef,                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
         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,  
         VECTOR * const currMV,  
         int32_t iMinSAD,  
         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 iFcode,  
         const int32_t iQuant,  
         const int32_t iEdgedWidth)  
 {  
 /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  
765    
766          int32_t iSAD;                          if (bDirection & 8)
767          VECTOR backupMV = *currMV;                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
768    
769          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);                          /* now we're doing diagonal checks near our candidate */
         CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);  
         CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);  
         CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);  
         CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);  
770    
771          return iMinSAD;                          if (iDirection)         //checking if anything found
772                            {
773                                    bDirection = iDirection;
774                                    iDirection = 0;
775                                    start_x = currMV->x;
776                                    start_y = currMV->y;
777                                    if (bDirection & 3)     //our candidate is left or right
778                                    {
779                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
780                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
781                                    } else                  // what remains here is up or down
782                                    {
783                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
784                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
785  }  }
786    
787  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)                                  if (iDirection) {
788                                            bDirection += iDirection;
789                                            start_x = currMV->x;
790                                            start_y = currMV->y;
791                                    }
792                            } else                          //about to quit, eh? not so fast....
793                            {
794                                    switch (bDirection) {
795                                    case 2:
796                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
797                                                                                             start_y - iDiamondSize, 2 + 4);
798                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
799                                                                                             start_y + iDiamondSize, 2 + 8);
800                                            break;
801                                    case 1:
802    
803                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
804                                                                                             start_y - iDiamondSize, 1 + 4);
805                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
806                                                                                             start_y + iDiamondSize, 1 + 8);
807                                            break;
808                                    case 2 + 4:
809                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
810                                                                                             start_y - iDiamondSize, 1 + 4);
811                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
812                                                                                             start_y - iDiamondSize, 2 + 4);
813                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
814                                                                                             start_y + iDiamondSize, 2 + 8);
815                                            break;
816                                    case 4:
817                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
818                                                                                             start_y - iDiamondSize, 2 + 4);
819                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
820                                                                                             start_y - iDiamondSize, 1 + 4);
821                                            break;
822                                    case 8:
823                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
824                                                                                             start_y + iDiamondSize, 2 + 8);
825                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
826                                                                                             start_y + iDiamondSize, 1 + 8);
827                                            break;
828                                    case 1 + 4:
829                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
830                                                                                             start_y + iDiamondSize, 1 + 8);
831                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
832                                                                                             start_y - iDiamondSize, 1 + 4);
833                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
834                                                                                             start_y - iDiamondSize, 2 + 4);
835                                            break;
836                                    case 2 + 8:
837                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
838                                                                                             start_y - iDiamondSize, 1 + 4);
839                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
840                                                                                             start_y + iDiamondSize, 1 + 8);
841                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
842                                                                                             start_y + iDiamondSize, 2 + 8);
843                                            break;
844                                    case 1 + 8:
845                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
846                                                                                             start_y - iDiamondSize, 2 + 4);
847                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
848                                                                                             start_y + iDiamondSize, 2 + 8);
849                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
850                                                                                             start_y + iDiamondSize, 1 + 8);
851                                            break;
852                                    default:                //1+2+4+8 == we didn't find anything at all
853                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
854                                                                                             start_y - iDiamondSize, 1 + 4);
855                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
856                                                                                             start_y + iDiamondSize, 1 + 8);
857                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
858                                                                                             start_y - iDiamondSize, 2 + 4);
859                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
860                                                                                             start_y + iDiamondSize, 2 + 8);
861                                            break;
862                                    }
863                                    if (!iDirection)
864                                            break;          //ok, the end. really
865                                    else {
866                                            bDirection = iDirection;
867                                            start_x = currMV->x;
868                                            start_y = currMV->y;
869                                    }
870                            }
871                    }
872                    while (1);                              //forever
873            }
874            return iMinSAD;
875    }
876    
877  int32_t PMVfastSearch16(  #define CHECK_MV16_F_INTERPOL(X,Y) { \
878                                          const uint8_t * const pRef,    if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
879                                          const uint8_t * const pRefH,      && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
880                                          const uint8_t * const pRefV,    { \
881                                          const uint8_t * const pRefHV,      iSAD = sad16bi( cur, \
882                                          const IMAGE * const pCur,                          get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
883                                          const int x, const int y,                          get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
884                                          const uint32_t MotionFlags,                          iEdgedWidth); \
885                                          const MBParam * const pParam,      iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
886                                          MACROBLOCK * const pMBs,      iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
887                                          VECTOR * const currMV,      if (iSAD < iMinSAD) \
888                                          VECTOR * const currPMV)      {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); } } \
889  {  }
         const uint32_t iWcount = pParam->mb_width;  
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
         const int32_t iWidth = pParam->width;  
         const int32_t iHeight = pParam->height;  
         const int32_t iEdgedWidth = pParam->edged_width;  
890    
891          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;  #define CHECK_MV16_F_INTERPOL_FOUND(X,Y) { \
892      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
893        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
894      { \
895        iSAD = sad16bi( cur, \
896                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
897                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
898                            iEdgedWidth); \
899        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
900        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
901        if (iSAD < iMinSAD) \
902        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); iFound=0;} } \
903    }
904    
905          int32_t iDiamondSize;  #define CHECK_MV16_B_INTERPOL(X,Y) { \
906      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
907        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
908      { \
909        iSAD = sad16bi( cur, \
910                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
911                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
912                            iEdgedWidth); \
913        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
914        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
915        if (iSAD < iMinSAD) \
916        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); } } \
917    }
918    
919    #define CHECK_MV16_B_INTERPOL_FOUND(X,Y) { \
920      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
921        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
922      { \
923        iSAD = sad16bi( cur, \
924                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
925                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
926                            iEdgedWidth); \
927        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
928        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
929        if (iSAD < iMinSAD) \
930        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); iFound=0;} } \
931    }
932    
933    int32_t
934    Diamond16_InterpolMainSearch(
935                                            const uint8_t * const f_pRef,
936                                             const uint8_t * const f_pRefH,
937                                             const uint8_t * const f_pRefV,
938                                             const uint8_t * const f_pRefHV,
939    
940                                             const uint8_t * const cur,
941    
942                                            const uint8_t * const b_pRef,
943                                             const uint8_t * const b_pRefH,
944                                             const uint8_t * const b_pRefV,
945                                             const uint8_t * const b_pRefHV,
946    
947                                             const int x,
948                                             const int y,
949    
950                                       const int f_start_x,
951                                       const int f_start_y,
952                                       const int b_start_x,
953                                       const int b_start_y,
954    
955                                       int iMinSAD,
956                                       VECTOR * const f_currMV,
957                                       VECTOR * const b_currMV,
958    
959                                       const int f_center_x,
960                                       const int f_center_y,
961                                       const int b_center_x,
962                                       const int b_center_y,
963    
964                                        const int32_t f_min_dx,
965                                            const int32_t f_max_dx,
966                                            const int32_t f_min_dy,
967                                            const int32_t f_max_dy,
968    
969                                        const int32_t b_min_dx,
970                                            const int32_t b_max_dx,
971                                            const int32_t b_min_dy,
972                                            const int32_t b_max_dy,
973    
974                                            const int32_t iEdgedWidth,
975                                            const int32_t iDiamondSize,
976    
977                                            const int32_t f_iFcode,
978                                            const int32_t b_iFcode,
979    
980                                            const int32_t iQuant,
981                                            int iFound)
982    {
983    /* Do a diamond search around given starting point, return SAD of best */
984    
985            int32_t iSAD;
986    
987            VECTOR f_backupMV;
988            VECTOR b_backupMV;
989    
990            f_currMV->x = f_start_x;
991            f_currMV->y = f_start_y;
992            b_currMV->x = b_start_x;
993            b_currMV->y = b_start_y;
994    
995            do
996            {
997                    iFound = 1;
998    
999                    f_backupMV = *f_currMV;
1000    
1001                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x - iDiamondSize, f_backupMV.y);
1002                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x + iDiamondSize, f_backupMV.y);
1003                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y - iDiamondSize);
1004                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y + iDiamondSize);
1005    
1006                    b_backupMV = *b_currMV;
1007    
1008                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x - iDiamondSize, b_backupMV.y);
1009                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x + iDiamondSize, b_backupMV.y);
1010                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y - iDiamondSize);
1011                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y + iDiamondSize);
1012    
1013            } while (!iFound);
1014    
1015            return iMinSAD;
1016    }
1017    
1018    /* Sorry, these MACROS really got too large... I'll turn them into function soon! */
1019    
1020    #define CHECK_MV16_DIRECT_FOUND(X,Y) \
1021            if ( (X)>=(-32) && (X)<=(31) && ((Y)>=-32) && ((Y)<=31) ) \
1022            { int k;\
1023            VECTOR mvs,b_mvs;       \
1024            iSAD = 0;\
1025            for (k = 0; k < 4; k++) {       \
1026                                            mvs.x = (int32_t) ((TRB * directmv[k].x) / TRD + (X));          \
1027                        b_mvs.x = (int32_t) (((X) == 0)                                                     \
1028                                                                                    ? ((TRB - TRD) * directmv[k].x) / TRD   \
1029                                                : mvs.x - directmv[k].x);                           \
1030                                                                                                                                                                    \
1031                        mvs.y = (int32_t) ((TRB * directmv[k].y) / TRD + (Y));              \
1032                            b_mvs.y = (int32_t) (((Y) == 0)                                                         \
1033                                                                                    ? ((TRB - TRD) * directmv[k].y) / TRD   \
1034                                                : mvs.y - directmv[k].y);                           \
1035                                                                                                                                                                    \
1036      if ( (mvs.x <= max_dx) && (mvs.x >= min_dx) \
1037        && (mvs.y <= max_dy) && (mvs.y >= min_dy)  \
1038            && (b_mvs.x <= max_dx) && (b_mvs.x >= min_dx)  \
1039        && (b_mvs.y <= max_dy) && (b_mvs.y >= min_dy) ) { \
1040                iSAD += sad8bi( cur + 8*(k&1) + 8*(k>>1)*iEdgedWidth,                                                                                                       \
1041                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1042                                            mvs.x, mvs.y, iEdgedWidth),                                                             \
1043                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1044                                            b_mvs.x, b_mvs.y, iEdgedWidth),                                                         \
1045                            iEdgedWidth); \
1046                    }       \
1047            else    \
1048                    iSAD = 65535;   \
1049            } \
1050            iSAD += calc_delta_16((X),(Y), 1, iQuant);\
1051            if (iSAD < iMinSAD) \
1052                {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iFound=0; } \
1053    }
1054    
1055    
1056    
1057    int32_t
1058    Diamond16_DirectMainSearch(
1059                                            const uint8_t * const f_pRef,
1060                                            const uint8_t * const f_pRefH,
1061                                            const uint8_t * const f_pRefV,
1062                                            const uint8_t * const f_pRefHV,
1063    
1064                                            const uint8_t * const cur,
1065    
1066                                            const uint8_t * const b_pRef,
1067                                            const uint8_t * const b_pRefH,
1068                                            const uint8_t * const b_pRefV,
1069                                            const uint8_t * const b_pRefHV,
1070    
1071                                            const int x,
1072                                            const int y,
1073    
1074                                            const int TRB,
1075                                            const int TRD,
1076    
1077                                        const int start_x,
1078                                        const int start_y,
1079    
1080                                        int iMinSAD,
1081                                        VECTOR * const currMV,
1082                                            const VECTOR * const directmv,
1083    
1084                                        const int32_t min_dx,
1085                                            const int32_t max_dx,
1086                                            const int32_t min_dy,
1087                                            const int32_t max_dy,
1088    
1089                                            const int32_t iEdgedWidth,
1090                                            const int32_t iDiamondSize,
1091    
1092                                            const int32_t iQuant,
1093                                            int iFound)
1094    {
1095    /* Do a diamond search around given starting point, return SAD of best */
1096    
1097            int32_t iSAD;
1098    
1099            VECTOR backupMV;
1100    
1101            currMV->x = start_x;
1102            currMV->y = start_y;
1103    
1104    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1105    
1106            do
1107            {
1108                    iFound = 1;
1109    
1110                    backupMV = *currMV;
1111    
1112                    CHECK_MV16_DIRECT_FOUND(backupMV.x - iDiamondSize, backupMV.y);
1113                    CHECK_MV16_DIRECT_FOUND(backupMV.x + iDiamondSize, backupMV.y);
1114                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y - iDiamondSize);
1115                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y + iDiamondSize);
1116    
1117            } while (!iFound);
1118    
1119            return iMinSAD;
1120    }
1121    
1122    
1123    int32_t
1124    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1125                                               const uint8_t * const pRefH,
1126                                               const uint8_t * const pRefV,
1127                                               const uint8_t * const pRefHV,
1128                                               const uint8_t * const cur,
1129                                               const int x,
1130                                               const int y,
1131                                               int start_x,
1132                                               int start_y,
1133                                               int iMinSAD,
1134                                               VECTOR * const currMV,
1135                                               const int center_x,
1136                                               const int center_y,
1137                                               const int32_t min_dx,
1138                                               const int32_t max_dx,
1139                                               const int32_t min_dy,
1140                                               const int32_t max_dy,
1141                                               const int32_t iEdgedWidth,
1142                                               const int32_t iDiamondSize,
1143                                               const int32_t iFcode,
1144                                               const int32_t iQuant,
1145                                               int iDirection)
1146    {
1147    
1148            int32_t iSAD;
1149    
1150    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1151    
1152            if (iDirection) {
1153                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1154                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1155                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1156                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1157            } else {
1158                    int bDirection = 1 + 2 + 4 + 8;
1159    
1160                    do {
1161                            iDirection = 0;
1162                            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)
1163                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1164    
1165                            if (bDirection & 2)
1166                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1167    
1168                            if (bDirection & 4)
1169                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1170    
1171                            if (bDirection & 8)
1172                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1173    
1174                            /* now we're doing diagonal checks near our candidate */
1175    
1176                            if (iDirection)         //checking if anything found
1177                            {
1178                                    bDirection = iDirection;
1179                                    iDirection = 0;
1180                                    start_x = currMV->x;
1181                                    start_y = currMV->y;
1182                                    if (bDirection & 3)     //our candidate is left or right
1183                                    {
1184                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1185                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1186                                    } else                  // what remains here is up or down
1187                                    {
1188                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1189                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1190                                    }
1191    
1192                                    if (iDirection) {
1193                                            bDirection += iDirection;
1194                                            start_x = currMV->x;
1195                                            start_y = currMV->y;
1196                                    }
1197                            } else                          //about to quit, eh? not so fast....
1198                            {
1199                                    switch (bDirection) {
1200                                    case 2:
1201                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1202                                                                                            start_y - iDiamondSize, 2 + 4);
1203                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1204                                                                                            start_y + iDiamondSize, 2 + 8);
1205                                            break;
1206                                    case 1:
1207                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1208                                                                                            start_y - iDiamondSize, 1 + 4);
1209                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1210                                                                                            start_y + iDiamondSize, 1 + 8);
1211                                            break;
1212                                    case 2 + 4:
1213                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1214                                                                                            start_y - iDiamondSize, 1 + 4);
1215                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1216                                                                                            start_y - iDiamondSize, 2 + 4);
1217                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1218                                                                                            start_y + iDiamondSize, 2 + 8);
1219                                            break;
1220                                    case 4:
1221                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1222                                                                                            start_y - iDiamondSize, 2 + 4);
1223                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1224                                                                                            start_y - iDiamondSize, 1 + 4);
1225                                            break;
1226                                    case 8:
1227                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1228                                                                                            start_y + iDiamondSize, 2 + 8);
1229                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1230                                                                                            start_y + iDiamondSize, 1 + 8);
1231                                            break;
1232                                    case 1 + 4:
1233                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1234                                                                                            start_y + iDiamondSize, 1 + 8);
1235                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1236                                                                                            start_y - iDiamondSize, 1 + 4);
1237                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1238                                                                                            start_y - iDiamondSize, 2 + 4);
1239                                            break;
1240                                    case 2 + 8:
1241                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1242                                                                                            start_y - iDiamondSize, 1 + 4);
1243                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1244                                                                                            start_y + iDiamondSize, 1 + 8);
1245                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1246                                                                                            start_y + iDiamondSize, 2 + 8);
1247                                            break;
1248                                    case 1 + 8:
1249                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1250                                                                                            start_y - iDiamondSize, 2 + 4);
1251                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1252                                                                                            start_y + iDiamondSize, 2 + 8);
1253                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1254                                                                                            start_y + iDiamondSize, 1 + 8);
1255                                            break;
1256                                    default:                //1+2+4+8 == we didn't find anything at all
1257                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1258                                                                                            start_y - iDiamondSize, 1 + 4);
1259                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1260                                                                                            start_y + iDiamondSize, 1 + 8);
1261                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1262                                                                                            start_y - iDiamondSize, 2 + 4);
1263                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1264                                                                                            start_y + iDiamondSize, 2 + 8);
1265                                            break;
1266                                    }
1267                                    if (!(iDirection))
1268                                            break;          //ok, the end. really
1269                                    else {
1270                                            bDirection = iDirection;
1271                                            start_x = currMV->x;
1272                                            start_y = currMV->y;
1273                                    }
1274                            }
1275                    }
1276                    while (1);                              //forever
1277            }
1278            return iMinSAD;
1279    }
1280    
1281    
1282    int32_t
1283    Full8_MainSearch(const uint8_t * const pRef,
1284                                     const uint8_t * const pRefH,
1285                                     const uint8_t * const pRefV,
1286                                     const uint8_t * const pRefHV,
1287                                     const uint8_t * const cur,
1288                                     const int x,
1289                                     const int y,
1290                               const int start_x,
1291                               const int start_y,
1292                               int iMinSAD,
1293                               VECTOR * const currMV,
1294                               const int center_x,
1295                               const int center_y,
1296                                     const int32_t min_dx,
1297                                     const int32_t max_dx,
1298                                     const int32_t min_dy,
1299                                     const int32_t max_dy,
1300                                     const int32_t iEdgedWidth,
1301                                     const int32_t iDiamondSize,
1302                                     const int32_t iFcode,
1303                                     const int32_t iQuant,
1304                                     int iFound)
1305    {
1306            int32_t iSAD;
1307            int32_t dx, dy;
1308            VECTOR backupMV;
1309    
1310            backupMV.x = start_x;
1311            backupMV.y = start_y;
1312    
1313            for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1314                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
1315                            NOCHECK_MV8_CANDIDATE(dx, dy);
1316    
1317            return iMinSAD;
1318    }
1319    
1320    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1321    
1322    int32_t
1323    Halfpel16_Refine(const uint8_t * const pRef,
1324                                     const uint8_t * const pRefH,
1325                                     const uint8_t * const pRefV,
1326                                     const uint8_t * const pRefHV,
1327                                     const uint8_t * const cur,
1328                                     const int x,
1329                                     const int y,
1330                                     VECTOR * const currMV,
1331                                     int32_t iMinSAD,
1332                               const int center_x,
1333                               const int center_y,
1334                                     const int32_t min_dx,
1335                                     const int32_t max_dx,
1336                                     const int32_t min_dy,
1337                                     const int32_t max_dy,
1338                                     const int32_t iFcode,
1339                                     const int32_t iQuant,
1340                                     const int32_t iEdgedWidth)
1341    {
1342    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1343    
1344            int32_t iSAD;
1345            VECTOR backupMV = *currMV;
1346    
1347            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1348            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y - 1);
1349            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1350            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y);
1351            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y);
1352            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1353            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y + 1);
1354            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1355    
1356            return iMinSAD;
1357    }
1358    
1359    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1360    
1361    
1362    
1363    int32_t
1364    PMVfastSearch16(const uint8_t * const pRef,
1365                                    const uint8_t * const pRefH,
1366                                    const uint8_t * const pRefV,
1367                                    const uint8_t * const pRefHV,
1368                                    const IMAGE * const pCur,
1369                                    const int x,
1370                                    const int y,
1371                                    const int start_x,      /* start is searched first, so it should contain the most */
1372                                    const int start_y,  /* likely motion vector for this block */
1373                                    const int center_x,     /* center is from where length of MVs is measured */
1374                                    const int center_y,
1375                                    const uint32_t MotionFlags,
1376                                    const uint32_t iQuant,
1377                                    const uint32_t iFcode,
1378                                    const MBParam * const pParam,
1379                                    const MACROBLOCK * const pMBs,
1380                                    const MACROBLOCK * const prevMBs,
1381                                    VECTOR * const currMV,
1382                                    VECTOR * const currPMV)
1383    {
1384            const uint32_t iWcount = pParam->mb_width;
1385            const int32_t iWidth = pParam->width;
1386            const int32_t iHeight = pParam->height;
1387            const int32_t iEdgedWidth = pParam->edged_width;
1388    
1389            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
1390    
1391            int32_t iDiamondSize;
1392    
1393          int32_t min_dx;          int32_t min_dx;
1394          int32_t max_dx;          int32_t max_dx;
# Line 808  Line 1403 
1403          VECTOR pmv[4];          VECTOR pmv[4];
1404          int32_t psad[4];          int32_t psad[4];
1405    
1406          MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1407    
1408            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1409    
1410          static int32_t threshA,threshB;          int32_t threshA, threshB;
1411          int32_t bPredEq;          int32_t bPredEq;
1412          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1413    
1414  /* Get maximum range */  /* Get maximum range */
1415          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1416                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1417    
1418  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1419    
1420          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1421          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1422          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1423          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1424          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1425          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1426    
1427          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1428            //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1429            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1430    
1431          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1432                  threshA =  512;                  threshA =  512;
1433                  threshB = 1024;                  threshB = 1024;
1434            } else {
         }  
         else  
         {  
1435                  threshA = psad[0];                  threshA = psad[0];
1436                  threshB = threshA+256;                  threshB = threshA+256;
1437                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1438                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1439                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1440                            threshA = 1024;
1441                    if (threshB > 1792)
1442                            threshB = 1792;
1443          }          }
1444    
1445          iFound=0;          iFound=0;
1446    
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
 */  
   
         if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )  
                 iDiamondSize=1; // halfpel!  
         else  
                 iDiamondSize=2; // halfpel!  
   
         if (!(MotionFlags & PMV_HALFPELDIAMOND16) )  
                 iDiamondSize*=2;  
   
1447  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1448     MinSAD=SAD     MinSAD=SAD
1449     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 874  Line 1451 
1451     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1452  */  */
1453    
1454            currMV->x = start_x;
1455            currMV->y = start_y;
1456    
1457  // Prepare for main loop          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
   
         *currMV=pmv[0];         /* current best := prediction */  
         if (!(MotionFlags & PMV_HALFPEL16 ))  
         {       /* This should NOT be necessary! */  
1458                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1459                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1460          }          }
1461    
1462          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1463                  currMV->x=max_dx;                  currMV->x=max_dx;
1464          }          }
1465          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1466                  currMV->x=min_dx;                  currMV->x=min_dx;
1467          }          }
1468          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1469                  currMV->y=max_dy;                  currMV->y=max_dy;
1470          }          }
1471          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1472                  currMV->y=min_dy;                  currMV->y=min_dy;
1473          }          }
1474    
1475          iMinSAD = sad16( cur,          iMinSAD =
1476                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1477                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1478          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1479            iMinSAD +=
1480          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1481          {                                            (uint8_t) iFcode, iQuant);
1482    
1483            if ((iMinSAD < 256) ||
1484                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1485                     ((int32_t) iMinSAD < prevMB->sad16))) {
1486                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1487                    {
1488                            if (!MVzero(*currMV)) {
1489                                    iMinSAD += MV16_00_BIAS;
1490                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1491                                    iMinSAD -= MV16_00_BIAS;
1492                            }
1493                    }
1494    
1495                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1496                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 915  Line 1498 
1498                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
1499          }          }
1500    
1501    
1502    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1503       vector of the median.
1504       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1505    */
1506    
1507            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1508                    iFound = 2;
1509    
1510    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1511       Otherwise select large Diamond Search.
1512    */
1513    
1514            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1515                    iDiamondSize = 1;               // halfpel!
1516            else
1517                    iDiamondSize = 2;               // halfpel!
1518    
1519            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1520                    iDiamondSize *= 2;
1521    
1522  /*  /*
1523     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
1524     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1525     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1526     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1527  */  */
1528    
1529  // (0,0) is always possible  // (0,0) is always possible
1530    
1531            if (!MVzero(pmv[0]))
1532          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1533    
1534  // previous frame MV is always possible  // previous frame MV is always possible
1535          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
1536            if (!MVzero(prevMB->mvs[0]))
1537                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1538                            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
1539    
1540  // left neighbour, if allowed  // left neighbour, if allowed
1541          if (x != 0)  
1542          {          if (!MVzero(pmv[1]))
1543                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1544                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1545                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1546                                            pmv[1].x = EVEN(pmv[1].x);
1547                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1548                  }                  }
1549    
1550                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1551          }          }
   
1552  // top neighbour, if allowed  // top neighbour, if allowed
1553          if (y != 0)          if (!MVzero(pmv[2]))
1554          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1555                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1556                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1557                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1558                                                    pmv[2].x = EVEN(pmv[2].x);
1559                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1560                  }                  }
1561                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1562    
1563  // top right neighbour, if allowed  // top right neighbour, if allowed
1564                  if (x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1565                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1566                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1567                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1568                                                                            if (!MVequal(pmv[3], pmv[2])) {
1569                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1570                                                                                            pmv[3].x = EVEN(pmv[3].x);
1571                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1572                          }                          }
1573                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1574                                                                                                                             pmv[3].y);
1575                  }                  }
1576          }          }
1577    
1578            if ((MVzero(*currMV)) &&
1579                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1580                    iMinSAD -= MV16_00_BIAS;
1581    
1582    
1583  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1584     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1585  */  */
1586    
1587          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1588          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1589                     ((int32_t) iMinSAD < prevMB->sad16))) {
1590                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1591                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1592                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 982  Line 1604 
1604     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1605  */  */
1606    
1607            if (MotionFlags & PMV_USESQUARES16)
1608                    MainSearchPtr = Square16_MainSearch;
1609            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1610                    MainSearchPtr = AdvDiamond16_MainSearch;
1611            else
1612                    MainSearchPtr = Diamond16_MainSearch;
1613    
1614          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1615    
1616    
1617  /* 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 */
1618          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1619                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1620                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1621                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1622                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1623                                                      iQuant, iFound);
1624    
1625          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1626                  *currMV = newMV;                  *currMV = newMV;
1627                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1628          }          }
1629    
1630          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1631  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1632    
1633                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1634                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1635                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1636                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1637                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1638                                                                      iDiamondSize, iFcode, iQuant, iFound);
1639    
1640                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1641                          *currMV = newMV;                          *currMV = newMV;
1642                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1643                  }                  }
1644                  }                  }
1645    
1646                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1647                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1648                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1649                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1650                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1651                                                                      iEdgedWidth, iDiamondSize, iFcode,
1652                                                                      iQuant, iFound);
1653    
1654                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1655                          *currMV = newMV;                          *currMV = newMV;
1656                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1657                  }                  }
# Line 1033  Line 1664 
1664    
1665  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1666          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1667                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1668                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1669                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1670                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1671    
1672  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1673          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1674          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1675          return iMinSAD;          return iMinSAD;
1676  }  }
1677    
# Line 1049  Line 1680 
1680    
1681    
1682    
1683  int32_t Diamond8_MainSearch(  int32_t
1684          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1685          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1686          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1687          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1688          const uint8_t * const cur,          const uint8_t * const cur,
1689          const int x, const int y,                                          const int x,
1690          int32_t startx, int32_t starty,                                          const int y,
1691                                            int32_t start_x,
1692                                            int32_t start_y,
1693          int32_t iMinSAD,          int32_t iMinSAD,
1694          VECTOR * const currMV,          VECTOR * const currMV,
1695          const VECTOR * const pmv,                                     const int center_x,
1696          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
1697          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1698                                            const int32_t max_dx,
1699                                            const int32_t min_dy,
1700                                            const int32_t max_dy,
1701          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1702          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1703          const int32_t iFcode,          const int32_t iFcode,
# Line 1071  Line 1707 
1707  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1708    
1709          int32_t iDirection=0;          int32_t iDirection=0;
1710            int32_t iDirectionBackup;
1711          int32_t iSAD;          int32_t iSAD;
1712          VECTOR backupMV;          VECTOR backupMV;
1713          backupMV.x = startx;  
1714          backupMV.y = starty;          backupMV.x = start_x;
1715            backupMV.y = start_y;
1716    
1717  /* 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 */
1718    
# Line 1083  Line 1721 
1721          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1722          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1723    
1724          if (iDirection)          if (iDirection) {
1725                  while (!iFound)                  while (!iFound) {
                 {  
1726                          iFound = 1;                          iFound = 1;
1727                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1728                            iDirectionBackup = iDirection;
1729    
1730                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1731                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1732                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1733                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1734                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1735                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1736                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1737                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1738                                                                                      backupMV.y - iDiamondSize, 3);
1739                            if (iDirectionBackup != 3)
1740                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1741                                                                                      backupMV.y + iDiamondSize, 4);
1742                  }                  }
1743          else          } else {
1744                    currMV->x = start_x;
1745                    currMV->y = start_y;
1746            }
1747            return iMinSAD;
1748    }
1749    
1750    
1751    
1752    
1753    int32_t
1754    Square8_MainSearch(const uint8_t * const pRef,
1755                                            const uint8_t * const pRefH,
1756                                            const uint8_t * const pRefV,
1757                                            const uint8_t * const pRefHV,
1758                                            const uint8_t * const cur,
1759                                            const int x,
1760                                            const int y,
1761                                            int32_t start_x,
1762                                            int32_t start_y,
1763                                            int32_t iMinSAD,
1764                                            VECTOR * const currMV,
1765                                       const int center_x,
1766                                       const int center_y,
1767                                            const int32_t min_dx,
1768                                            const int32_t max_dx,
1769                                            const int32_t min_dy,
1770                                            const int32_t max_dy,
1771                                            const int32_t iEdgedWidth,
1772                                            const int32_t iDiamondSize,
1773                                            const int32_t iFcode,
1774                                            const int32_t iQuant,
1775                                            int iFound)
1776          {          {
1777                  currMV->x = startx;  /* Do a square search around given starting point, return SAD of best */
1778                  currMV->y = starty;  
1779            int32_t iDirection = 0;
1780            int32_t iSAD;
1781            VECTOR backupMV;
1782    
1783            backupMV.x = start_x;
1784            backupMV.y = start_y;
1785    
1786    /* It's one search with full square pattern, and new parts for all following diamonds */
1787    
1788    /*   new direction are extra, so 1-4 is normal diamond
1789          537
1790          1*2
1791          648
1792    */
1793    
1794            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1795            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1796            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1797            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1798    
1799            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1800                                                             backupMV.y - iDiamondSize, 5);
1801            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1802                                                             backupMV.y + iDiamondSize, 6);
1803            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1804                                                             backupMV.y - iDiamondSize, 7);
1805            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1806                                                             backupMV.y + iDiamondSize, 8);
1807    
1808    
1809            if (iDirection) {
1810                    while (!iFound) {
1811                            iFound = 1;
1812                            backupMV = *currMV;
1813    
1814                            switch (iDirection) {
1815                            case 1:
1816                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1817                                                                                       backupMV.y, 1);
1818                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1819                                                                                     backupMV.y - iDiamondSize, 5);
1820                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1821                                                                                     backupMV.y - iDiamondSize, 7);
1822                                    break;
1823                            case 2:
1824                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1825                                                                                     2);
1826                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1827                                                                                     backupMV.y + iDiamondSize, 6);
1828                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1829                                                                                     backupMV.y + iDiamondSize, 8);
1830                                    break;
1831    
1832                            case 3:
1833                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1834                                                                                     4);
1835                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1836                                                                                     backupMV.y - iDiamondSize, 7);
1837                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1838                                                                                     backupMV.y + iDiamondSize, 8);
1839                                    break;
1840    
1841                            case 4:
1842                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1843                                                                                     3);
1844                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1845                                                                                     backupMV.y - iDiamondSize, 5);
1846                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1847                                                                                     backupMV.y + iDiamondSize, 6);
1848                                    break;
1849    
1850                            case 5:
1851                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1852                                                                                     1);
1853                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1854                                                                                     3);
1855                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1856                                                                                     backupMV.y - iDiamondSize, 5);
1857                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1858                                                                                     backupMV.y + iDiamondSize, 6);
1859                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1860                                                                                     backupMV.y - iDiamondSize, 7);
1861                                    break;
1862    
1863                            case 6:
1864                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1865                                                                                     2);
1866                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1867                                                                                     3);
1868    
1869                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1870                                                                                     backupMV.y - iDiamondSize, 5);
1871                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1872                                                                                     backupMV.y + iDiamondSize, 6);
1873                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1874                                                                                     backupMV.y + iDiamondSize, 8);
1875    
1876                                    break;
1877    
1878                            case 7:
1879                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1880                                                                                       backupMV.y, 1);
1881                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1882                                                                                     4);
1883                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1884                                                                                     backupMV.y - iDiamondSize, 5);
1885                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1886                                                                                     backupMV.y - iDiamondSize, 7);
1887                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1888                                                                                     backupMV.y + iDiamondSize, 8);
1889                                    break;
1890    
1891                            case 8:
1892                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1893                                                                                     2);
1894                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1895                                                                                     4);
1896                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1897                                                                                     backupMV.y + iDiamondSize, 6);
1898                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1899                                                                                     backupMV.y - iDiamondSize, 7);
1900                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1901                                                                                     backupMV.y + iDiamondSize, 8);
1902                                    break;
1903                            default:
1904                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1905                                                                                     1);
1906                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1907                                                                                     2);
1908                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1909                                                                                     3);
1910                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1911                                                                                     4);
1912    
1913                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1914                                                                                     backupMV.y - iDiamondSize, 5);
1915                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1916                                                                                     backupMV.y + iDiamondSize, 6);
1917                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1918                                                                                     backupMV.y - iDiamondSize, 7);
1919                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1920                                                                                     backupMV.y + iDiamondSize, 8);
1921                                    break;
1922                            }
1923                    }
1924            } else {
1925                    currMV->x = start_x;
1926                    currMV->y = start_y;
1927          }          }
1928          return iMinSAD;          return iMinSAD;
1929  }  }
1930    
1931  int32_t Halfpel8_Refine(  
1932          const uint8_t * const pRef,  
1933    
1934    
1935    int32_t
1936    Halfpel8_Refine_c(const uint8_t * const pRef,
1937          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1938          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1939          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1940          const uint8_t * const cur,          const uint8_t * const cur,
1941          const int x, const int y,                                  const int x,
1942                                    const int y,
1943          VECTOR * const currMV,          VECTOR * const currMV,
1944          int32_t iMinSAD,          int32_t iMinSAD,
1945          const VECTOR * const pmv,                             const int center_x,
1946          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1947          const int32_t min_dy, const int32_t max_dy,                                  const int32_t min_dx,
1948                                    const int32_t max_dx,
1949                                    const int32_t min_dy,
1950                                    const int32_t max_dy,
1951          const int32_t iFcode,          const int32_t iFcode,
1952          const int32_t iQuant,          const int32_t iQuant,
1953          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1142  Line 1972 
1972    
1973  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1974    
1975  int32_t PMVfastSearch8(  int32_t
1976                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1977                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1978                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1979                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1980                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1981                                          const int x, const int y,                             const int x,
1982                                          const int start_x, int start_y,                             const int y,
1983                               const int start_x,
1984                               const int start_y,
1985                                    const int center_x,
1986                                    const int center_y,
1987                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1988                               const uint32_t iQuant,
1989                               const uint32_t iFcode,
1990                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1991                                          MACROBLOCK * const pMBs,                             const MACROBLOCK * const pMBs,
1992                               const MACROBLOCK * const prevMBs,
1993                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1994                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1995  {  {
1996          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
   
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
1997          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1998          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1999          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 1177  Line 2011 
2011          int32_t psad[4];          int32_t psad[4];
2012          VECTOR newMV;          VECTOR newMV;
2013          VECTOR backupMV;          VECTOR backupMV;
2014            VECTOR startMV;
2015    
2016          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2017            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2018    
2019          static int32_t threshA,threshB;           int32_t threshA, threshB;
2020          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
2021          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
2022    
2023          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
2024    
2025  /* Get maximum range */          MainSearch8FuncPtr MainSearchPtr;
         get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                   x, y, 8, iWidth, iHeight, iFcode);  
2026    
2027  /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */          /* Init variables */
2028            startMV.x = start_x;
2029            startMV.y = start_y;
2030    
2031          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          /* Get maximum range */
2032          { min_dx = EVEN(min_dx);          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2033                              iFcode);
2034    
2035            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
2036                    min_dx = EVEN(min_dx);
2037          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
2038          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
2039          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
2040          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
   
         bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);  
   
         if ((x==0) && (y==0) )  
         {  
                 threshA =  512/4;  
                 threshB = 1024/4;  
   
         }  
         else  
         {  
                 threshA = psad[0]/4;                    /* good estimate */  
                 threshB = threshA+256/4;  
                 if (threshA< 512/4) threshA =  512/4;  
                 if (threshA>1024/4) threshA = 1024/4;  
                 if (threshB>1792/4) threshB = 1792/4;  
         }  
   
         iFound=0;  
   
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
2041    
2042          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
2043                  iFound=2;          //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
2044            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
2045    
2046  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.          if ((x == 0) && (y == 0)) {
2047     Otherwise select large Diamond Search.                  threshA = 512 / 4;
2048  */                  threshB = 1024 / 4;
2049    
2050          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )          } else {
2051                  iDiamondSize=1; // 1 halfpel!                  threshA = psad[0] / 4;  /* good estimate? */
2052          else                  threshB = threshA + 256 / 4;
2053                  iDiamondSize=2; // 2 halfpel = 1 full pixel!                  if (threshA < 512 / 4)
2054                            threshA = 512 / 4;
2055                    if (threshA > 1024 / 4)
2056                            threshA = 1024 / 4;
2057                    if (threshB > 1792 / 4)
2058                            threshB = 1792 / 4;
2059            }
2060    
2061          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )          iFound = 0;
                 iDiamondSize*=2;  
2062    
2063  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2064     MinSAD=SAD     MinSAD=SAD
# Line 1249  Line 2070 
2070    
2071  // Prepare for main loop  // Prepare for main loop
2072    
2073          currMV->x=start_x;              /* start with mv16 */    if (MotionFlags & PMV_USESQUARES8)
2074          currMV->y=start_y;        MainSearchPtr = Square8_MainSearch;
2075      else
2076    
2077            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2078                    MainSearchPtr = AdvDiamond8_MainSearch;
2079            else
2080                    MainSearchPtr = Diamond8_MainSearch;
2081    
         iMinSAD = sad8( cur,  
                         get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),  
                         iEdgedWidth);  
         iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;  
2082    
2083          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          *currMV = startMV;
2084          {  
2085            iMinSAD =
2086                    sad8(cur,
2087                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2088                                                    iEdgedWidth), iEdgedWidth);
2089            iMinSAD +=
2090                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2091                                             (uint8_t) iFcode, iQuant);
2092    
2093            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
2094                                                                    && ((int32_t) iMinSAD <
2095                                                                            prevMB->sad8[iSubBlock]))) {
2096                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2097                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2098                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
2099                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
2100          }          }
2101    
2102    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2103       vector of the median.
2104       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2105    */
2106    
2107            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
2108                    iFound = 2;
2109    
2110    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2111       Otherwise select large Diamond Search.
2112    */
2113    
2114            if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
2115                    iDiamondSize = 1;               // 1 halfpel!
2116            else
2117                    iDiamondSize = 2;               // 2 halfpel = 1 full pixel!
2118    
2119            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2120                    iDiamondSize *= 2;
2121    
2122    
2123  /*  /*
2124     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2125     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
2126     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
2127     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
2128  */  */
2129    
2130  // the prediction might be even better than mv16  // the median prediction might be even better than mv16
         CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);  
2131    
2132  // (0,0) is always possible          if (!MVequal(pmv[0], startMV))
2133                    CHECK_MV8_CANDIDATE(center_x, center_y);
2134    
2135    // (0,0) if needed
2136            if (!MVzero(pmv[0]))
2137                    if (!MVzero(startMV))
2138          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2139    
2140  // previous frame MV is always possible  // previous frame MV if needed
2141          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
2142                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
2143                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
2144                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
2145                                                                            prevMB->mvs[iSubBlock].y);
2146    
2147            if ((iMinSAD <= threshA) ||
2148                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2149                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2150                    if (MotionFlags & PMV_QUICKSTOP16)
2151                            goto PMVfast8_Terminate_without_Refine;
2152                    if (MotionFlags & PMV_EARLYSTOP16)
2153                            goto PMVfast8_Terminate_with_Refine;
2154            }
2155    
2156  // left neighbour, if allowed  // left neighbour, if allowed and needed
2157          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
2158          {                  if (!MVequal(pmv[1], startMV))
2159                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
2160                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
2161                                            if (!(MotionFlags & PMV_HALFPEL8)) {
2162                                                    pmv[1].x = EVEN(pmv[1].x);
2163                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
2164                  }                  }
2165                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2166          }          }
2167    // top neighbour, if allowed and needed
2168  // top neighbour, if allowed          if (!MVzero(pmv[2]))
2169          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
2170          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
2171                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
2172                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
2173                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
2174                                                            pmv[2].x = EVEN(pmv[2].x);
2175                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
2176                  }                  }
2177                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2178    
2179  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
2180                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
2181                  {                                                          if (!MVequal(pmv[3], startMV))
2182                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
2183                          {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
2184                                                                                    if (!MVequal(pmv[3], pmv[1]))
2185                                                                                            if (!MVequal(pmv[3], pmv[2])) {
2186                                                                                                    if (!
2187                                                                                                            (MotionFlags &
2188                                                                                                             PMV_HALFPEL8)) {
2189                                                                                                            pmv[3].x = EVEN(pmv[3].x);
2190                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
2191                          }                          }
2192                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
2193                                                                                                                                            pmv[3].y);
2194                  }                  }
2195          }          }
2196    
2197            if ((MVzero(*currMV)) &&
2198                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2199                    iMinSAD -= MV8_00_BIAS;
2200    
2201    
2202  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
2203     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2204  */  */
2205    
2206          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2207          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2208                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2209                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2210                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2211                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1337  Line 2225 
2225          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2226    
2227  /* 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 */
2228          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2229                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2230                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2231                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2232                                                      iQuant, iFound);
2233    
2234          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2235                  *currMV = newMV;                  *currMV = newMV;
2236                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2237          }          }
2238    
2239          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2240  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
2241    
2242                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2243                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2244                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2245                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2246                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2247                                                                      iDiamondSize, iFcode, iQuant, iFound);
2248    
2249                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2250                          *currMV = newMV;                          *currMV = newMV;
2251                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2252                  }                  }
2253                  }                  }
2254    
2255                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2256                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2257                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2258                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2259                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2260                                                                      iQuant, iFound);
2261    
2262                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2263                          *currMV = newMV;                          *currMV = newMV;
2264                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2265                  }                  }
# Line 1385  Line 2272 
2272    
2273  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
2274          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2275                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2276                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2277                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2278                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2279    
2280    
2281  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
2282          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2283          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2284    
2285          return iMinSAD;          return iMinSAD;
2286  }  }
2287    
2288  int32_t EPZSSearch16(  int32_t
2289                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2290                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2291                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2292                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2293                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2294                                          const int x, const int y,                           const int x,
2295                             const int y,
2296                            const int start_x,
2297                            const int start_y,
2298                            const int center_x,
2299                            const int center_y,
2300                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2301                             const uint32_t iQuant,
2302                             const uint32_t iFcode,
2303                                          const MBParam * const pParam,                                          const MBParam * const pParam,
2304                                          MACROBLOCK * const pMBs,                           const MACROBLOCK * const pMBs,
2305                             const MACROBLOCK * const prevMBs,
2306                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2307                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2308  {  {
2309          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
2310          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
2311    
2312          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2313          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
# Line 1434  Line 2327 
2327          int32_t psad[8];          int32_t psad[8];
2328    
2329          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2330          MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
2331    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2332            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2333          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
2334    
2335          static int32_t thresh2;           int32_t thresh2;
2336          int32_t bPredEq;          int32_t bPredEq;
2337          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2338    
2339          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2340    
2341          if (oldMBs == NULL)          if (oldMBs == NULL) {
2342          {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2343                  fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2344          }          }
2345          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2346    
2347  /* Get maximum range */  /* Get maximum range */
2348          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2349                          x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
2350    
2351  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */          if (!(MotionFlags & PMV_HALFPEL16)) {
2352                    min_dx = EVEN(min_dx);
         if (!(MotionFlags & PMV_HALFPEL16 ))  
         { min_dx = EVEN(min_dx);  
2353            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2354            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2355            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2356          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2357            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2358          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2359            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2360    
2361  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2362          MinSAD=SAD          MinSAD=SAD
# Line 1473  Line 2367 
2367    
2368  // Prepare for main loop  // Prepare for main loop
2369    
2370          *currMV=pmv[0];         /* current best := median prediction */          currMV->x = start_x;
2371          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2372          {  
2373            if (!(MotionFlags & PMV_HALFPEL16)) {
2374                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2375                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2376          }          }
# Line 1491  Line 2386 
2386    
2387  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2388    
2389          iMinSAD = sad16( cur,          iMinSAD =
2390                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2391                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2392          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2393            iMinSAD +=
2394                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2395                                              (uint8_t) iFcode, iQuant);
2396    
2397  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2398          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD < 256) ||
2399                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2400                     ((int32_t) iMinSAD < prevMB->sad16))) {
2401                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2402                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2403                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1508  Line 2407 
2407  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2408    
2409  // previous frame MV  // previous frame MV
2410          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
2411    
2412  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2413  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
2414    
2415          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2416                  thresh2 =  512;                  thresh2 =  512;
2417          }          } else {
         else  
         {  
2418  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
2419    
2420                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1530  Line 2426 
2426    
2427    
2428  // left neighbour, if allowed  // left neighbour, if allowed
2429          if (x != 0)          if (x != 0) {
2430          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2431                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2432                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2433                  }                  }
2434                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2435          }          }
   
2436  // top neighbour, if allowed  // top neighbour, if allowed
2437          if (y != 0)          if (y != 0) {
2438          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2439                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2440                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2441                  }                  }
2442                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
2443    
2444  // top right neighbour, if allowed  // top right neighbour, if allowed
2445                  if (x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
2446                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2447                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2448                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2449                          }                          }
2450                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1564  Line 2456 
2456  */  */
2457    
2458          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2459                  || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD <= pMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2460                  {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2461                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2462                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2463                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1574  Line 2466 
2466    
2467  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
2468    
2469          backupMV = pMB->mvs[0];                 // last MV          backupMV = prevMB->mvs[0];      // collocated MV
2470          backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X          backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2471          backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y          backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2472    
2473            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y);
2474    
2475    // left neighbour
2476            if (x != 0)
2477                    CHECK_MV16_CANDIDATE((prevMB - 1)->mvs[0].x, (prevMB - 1)->mvs[0].y);
2478    
2479    // top neighbour
2480            if (y != 0)
2481                    CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2482                                                             (prevMB - iWcount)->mvs[0].y);
2483    
2484    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2485    
2486            if ((uint32_t) x != iWcount - 1)
2487                    CHECK_MV16_CANDIDATE((prevMB + 1)->mvs[0].x, (prevMB + 1)->mvs[0].y);
2488    
2489    // bottom neighbour, dito
2490            if ((uint32_t) y != iHcount - 1)
2491                    CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2492                                                             (prevMB + iWcount)->mvs[0].y);
2493    
2494    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2495            if (iMinSAD <= thresh2) {
2496                    if (MotionFlags & PMV_QUICKSTOP16)
2497                            goto EPZS16_Terminate_without_Refine;
2498                    if (MotionFlags & PMV_EARLYSTOP16)
2499                            goto EPZS16_Terminate_with_Refine;
2500            }
2501    
2502    /************ (if Diamond Search)  **************/
2503    
2504            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2505    
2506            if (MotionFlags & PMV_USESQUARES16)
2507                    MainSearchPtr = Square16_MainSearch;
2508            else
2509             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2510                    MainSearchPtr = AdvDiamond16_MainSearch;
2511            else
2512                    MainSearchPtr = Diamond16_MainSearch;
2513    
2514    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2515    
2516            iSAD =
2517                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2518                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2519                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2520    
2521            if (iSAD < iMinSAD) {
2522                    *currMV = newMV;
2523                    iMinSAD = iSAD;
2524            }
2525    
2526    
2527            if (MotionFlags & PMV_EXTSEARCH16) {
2528    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2529    
2530                    if (!(MVequal(pmv[0], backupMV))) {
2531                            iSAD =
2532                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2533                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2534                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2535                                                                      2, iFcode, iQuant, 0);
2536                    }
2537    
2538                    if (iSAD < iMinSAD) {
2539                            *currMV = newMV;
2540                            iMinSAD = iSAD;
2541                    }
2542    
2543                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2544                            iSAD =
2545                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2546                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2547                                                                      max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2548    
2549                            if (iSAD < iMinSAD) {
2550                                    *currMV = newMV;
2551                                    iMinSAD = iSAD;
2552                            }
2553                    }
2554            }
2555    
2556    /***************        Choose best MV found     **************/
2557    
2558      EPZS16_Terminate_with_Refine:
2559            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2560                    iMinSAD =
2561                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2562                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2563                                                             iFcode, iQuant, iEdgedWidth);
2564    
2565      EPZS16_Terminate_without_Refine:
2566    
2567            *oldMB = *prevMB;
2568    
2569            currPMV->x = currMV->x - center_x;
2570            currPMV->y = currMV->y - center_y;
2571            return iMinSAD;
2572    }
2573    
2574    
2575    int32_t
2576    EPZSSearch8(const uint8_t * const pRef,
2577                            const uint8_t * const pRefH,
2578                            const uint8_t * const pRefV,
2579                            const uint8_t * const pRefHV,
2580                            const IMAGE * const pCur,
2581                            const int x,
2582                            const int y,
2583                            const int start_x,
2584                            const int start_y,
2585                            const int center_x,
2586                            const int center_y,
2587                            const uint32_t MotionFlags,
2588                            const uint32_t iQuant,
2589                            const uint32_t iFcode,
2590                            const MBParam * const pParam,
2591                            const MACROBLOCK * const pMBs,
2592                            const MACROBLOCK * const prevMBs,
2593                            VECTOR * const currMV,
2594                            VECTOR * const currPMV)
2595    {
2596    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
2597    
2598            const uint32_t iWcount = pParam->mb_width;
2599            const int32_t iWidth = pParam->width;
2600            const int32_t iHeight = pParam->height;
2601            const int32_t iEdgedWidth = pParam->edged_width;
2602    
2603            const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;
2604    
2605            int32_t iDiamondSize = 1;
2606    
2607            int32_t min_dx;
2608            int32_t max_dx;
2609            int32_t min_dy;
2610            int32_t max_dy;
2611    
2612            VECTOR newMV;
2613            VECTOR backupMV;
2614    
2615            VECTOR pmv[4];
2616            int32_t psad[8];
2617    
2618            const int32_t iSubBlock = ((y & 1) << 1) + (x & 1);
2619    
2620    //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2621            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2622    
2623            int32_t bPredEq;
2624            int32_t iMinSAD, iSAD = 9999;
2625    
2626            MainSearch8FuncPtr MainSearchPtr;
2627    
2628    /* Get maximum range */
2629            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2630                              iFcode);
2631    
2632    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2633    
2634            if (!(MotionFlags & PMV_HALFPEL8)) {
2635                    min_dx = EVEN(min_dx);
2636                    max_dx = EVEN(max_dx);
2637                    min_dy = EVEN(min_dy);
2638                    max_dy = EVEN(max_dy);
2639            }
2640            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2641            //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv[0].x, pmv[0].y, psad);
2642            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2643    
2644    
2645    /* Step 4: Calculate SAD around the Median prediction.
2646            MinSAD=SAD
2647            If Motion Vector equal to Previous frame motion vector
2648                    and MinSAD<PrevFrmSAD goto Step 10.
2649            If SAD<=256 goto Step 10.
2650    */
2651    
2652    // Prepare for main loop
2653    
2654    
2655            if (!(MotionFlags & PMV_HALFPEL8)) {
2656                    currMV->x = EVEN(currMV->x);
2657                    currMV->y = EVEN(currMV->y);
2658            }
2659    
2660            if (currMV->x > max_dx)
2661                    currMV->x = max_dx;
2662            if (currMV->x < min_dx)
2663                    currMV->x = min_dx;
2664            if (currMV->y > max_dy)
2665                    currMV->y = max_dy;
2666            if (currMV->y < min_dy)
2667                    currMV->y = min_dy;
2668    
2669    /***************** This is predictor SET A: only median prediction ******************/
2670    
2671    
2672            iMinSAD =
2673                    sad8(cur,
2674                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2675                                                    iEdgedWidth), iEdgedWidth);
2676            iMinSAD +=
2677                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2678                                             (uint8_t) iFcode, iQuant);
2679    
2680    
2681    // thresh1 is fixed to 256
2682            if (iMinSAD < 256 / 4) {
2683                    if (MotionFlags & PMV_QUICKSTOP8)
2684                            goto EPZS8_Terminate_without_Refine;
2685                    if (MotionFlags & PMV_EARLYSTOP8)
2686                            goto EPZS8_Terminate_with_Refine;
2687            }
2688    
2689    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2690    
2691    
2692    // MV=(0,0) is often a good choice
2693            CHECK_MV8_ZERO;
2694    
2695    // previous frame MV
2696            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2697    
2698    // left neighbour, if allowed
2699            if (psad[1] != MV_MAX_ERROR) {
2700                    if (!(MotionFlags & PMV_HALFPEL8)) {
2701                            pmv[1].x = EVEN(pmv[1].x);
2702                            pmv[1].y = EVEN(pmv[1].y);
2703                    }
2704                    CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2705            }
2706    // top neighbour, if allowed
2707            if (psad[2] != MV_MAX_ERROR) {
2708                    if (!(MotionFlags & PMV_HALFPEL8)) {
2709                            pmv[2].x = EVEN(pmv[2].x);
2710                            pmv[2].y = EVEN(pmv[2].y);
2711                    }
2712                    CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2713    
2714    // top right neighbour, if allowed
2715                    if (psad[3] != MV_MAX_ERROR) {
2716                            if (!(MotionFlags & PMV_HALFPEL8)) {
2717                                    pmv[3].x = EVEN(pmv[3].x);
2718                                    pmv[3].y = EVEN(pmv[3].y);
2719                            }
2720                            CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2721                    }
2722            }
2723    
2724    /*  // this bias is zero anyway, at the moment!
2725    
2726          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2727                    iMinSAD -= MV8_00_BIAS;
2728    
2729  // left neighbour  */
         if (x != 0)  
                 CHECK_MV16_CANDIDATE((oldMB-1)->mvs[0].x,oldMB->mvs[0].y);  
2730    
2731  // top neighbour  /* Terminate if MinSAD <= T_2
2732          if (y != 0)     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2733                  CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);  */
2734    
2735  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
2736                    if (MotionFlags & PMV_QUICKSTOP8)
2737                            goto EPZS8_Terminate_without_Refine;
2738                    if (MotionFlags & PMV_EARLYSTOP8)
2739                            goto EPZS8_Terminate_with_Refine;
2740            }
2741    
2742          if (x != iWcount-1)  /************ (Diamond Search)  **************/
                 CHECK_MV16_CANDIDATE((pMB+1)->mvs[0].x,oldMB->mvs[0].y);  
2743    
2744  // bottom neighbour, dito          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
         if (y != iHcount-1)  
                 CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);  
2745    
2746  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */          if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2747          if (iMinSAD <= thresh2)                  iDiamondSize *= 2;
                 {  
                         if (MotionFlags & PMV_QUICKSTOP16)  
                                 goto EPZS16_Terminate_without_Refine;  
                         if (MotionFlags & PMV_EARLYSTOP16)  
                                 goto EPZS16_Terminate_with_Refine;  
                 }  
2748    
2749  /************ (if Diamond Search)  **************/  /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2750    
2751          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */  // there is no EPZS^2 for inter4v at the moment
2752    
2753  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */    if (MotionFlags & PMV_USESQUARES8)
2754          MainSearchPtr = Square8_MainSearch;
2755      else
2756    
2757          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2758                  EPZSMainSearchPtr = Square16_MainSearch;                  MainSearchPtr = AdvDiamond8_MainSearch;
2759          else          else
2760                  EPZSMainSearchPtr = Diamond16_MainSearch;                  MainSearchPtr = Diamond8_MainSearch;
2761    
2762          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2763                          x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2764                          currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2765                          2, iFcode, iQuant, 0);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2766                                                      iQuant, 0);
2767    
2768          if (iSAD < iMinSAD)  
2769          {          if (iSAD < iMinSAD) {
2770                  *currMV = newMV;                  *currMV = newMV;
2771                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2772          }          }
2773    
2774            if (MotionFlags & PMV_EXTSEARCH8) {
         if (MotionFlags & PMV_EXTSEARCH16)  
         {  
2775  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2776    
2777                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2778                  {                          iSAD =
2779                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2780                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2781                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2782                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
                 }  
2783    
2784                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2785                          *currMV = newMV;                          *currMV = newMV;
2786                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2787                  }                  }
2788                    }
2789    
2790                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2791                  {                          iSAD =
2792                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2793                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2794                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2795                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, /*iDiamondSize*/ 2, iFcode, iQuant, 0);                                                                    iQuant, 0);
2796    
2797                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2798                                  *currMV = newMV;                                  *currMV = newMV;
2799                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2800                          }                          }
# Line 1664  Line 2803 
2803    
2804  /***************        Choose best MV found     **************/  /***************        Choose best MV found     **************/
2805    
2806  EPZS16_Terminate_with_Refine:    EPZS8_Terminate_with_Refine:
2807          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2808                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2809                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2810                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2811                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
   
 EPZS16_Terminate_without_Refine:  
2812    
2813          *oldMB = *pMB;    EPZS8_Terminate_without_Refine:
2814    
2815          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2816          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2817          return iMinSAD;          return iMinSAD;
2818  }  }
2819    
2820    
2821  int32_t EPZSSearch8(  
2822                                          const uint8_t * const pRef,  int32_t
2823    PMVfastIntSearch16(const uint8_t * const pRef,
2824                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2825                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2826                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2827                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2828                                          const int x, const int y,                                  const int x,
2829                                          const int start_x, const int start_y,                                  const int y,
2830                                    const int start_x,              /* start should be most likely vector */
2831                                    const int start_y,
2832                                    const int center_x,             /* center is from where length of MVs is measured */
2833                                    const int center_y,
2834                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2835                                    const uint32_t iQuant,
2836                                    const uint32_t iFcode,
2837                                          const MBParam * const pParam,                                          const MBParam * const pParam,
2838                                          MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
2839                                    const MACROBLOCK * const prevMBs,
2840                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2841                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2842  {  {
2843          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
   
2844          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2845          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
2846          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
2847    
2848          const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;          const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2849            const VECTOR zeroMV = { 0, 0 };
2850    
2851          int32_t iDiamondSize=1;          int32_t iDiamondSize;
2852    
2853          int32_t min_dx;          int32_t min_dx;
2854          int32_t max_dx;          int32_t max_dx;
2855          int32_t min_dy;          int32_t min_dy;
2856          int32_t max_dy;          int32_t max_dy;
2857    
2858            int32_t iFound;
2859    
2860          VECTOR newMV;          VECTOR newMV;
2861          VECTOR backupMV;          VECTOR backupMV;
2862    
2863          VECTOR pmv[4];          VECTOR pmv[4];
2864          int32_t psad[8];          int32_t psad[4];
2865    
2866          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          MainSearch16FuncPtr MainSearchPtr;
2867    
2868          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2869            MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2870    
2871            int32_t threshA, threshB;
2872          int32_t bPredEq;          int32_t bPredEq;
2873          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD, iSAD;
2874    
         MainSearch8FuncPtr EPZSMainSearchPtr;  
2875    
2876  /* Get maximum range */  /* Get maximum range */
2877          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2878                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2879    
2880  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2881    
2882          if (!(MotionFlags & PMV_HALFPEL8 ))          if ((x == 0) && (y == 0)) {
2883          { min_dx = EVEN(min_dx);                  threshA = 512;
2884            max_dx = EVEN(max_dx);                  threshB = 1024;
2885            min_dy = EVEN(min_dy);  
2886            max_dy = EVEN(max_dy);                  bPredEq = 0;
2887          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */                  psad[0] = psad[1] = psad[2] = psad[3] = 0;
2888                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2889    
2890          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);          } else {
2891                    threshA = psad[0];
2892                    threshB = threshA + 256;
2893                    if (threshA < 512)
2894                            threshA = 512;
2895                    if (threshA > 1024)
2896                            threshA = 1024;
2897                    if (threshB > 1792)
2898                            threshB = 1792;
2899    
2900                    bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2901                    *currMV = pmv[0];                       /* current best := prediction */
2902            }
2903    
2904            iFound = 0;
2905    
2906  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2907          MinSAD=SAD          MinSAD=SAD
# Line 1750  Line 2910 
2910          If SAD<=256 goto Step 10.          If SAD<=256 goto Step 10.
2911  */  */
2912    
2913  // Prepare for main loop          if (currMV->x > max_dx) {
2914                    currMV->x = EVEN(max_dx);
2915            }
2916            if (currMV->x < min_dx) {
2917                    currMV->x = EVEN(min_dx);
2918            }
2919            if (currMV->y > max_dy) {
2920                    currMV->y = EVEN(max_dy);
2921            }
2922            if (currMV->y < min_dy) {
2923                    currMV->y = EVEN(min_dy);
2924            }
2925    
2926            iMinSAD =
2927                    sad16(cur,
2928                              get_iref_mv(pRef, x, y, 16, currMV,
2929                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2930            iMinSAD +=
2931                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2932                                              (uint8_t) iFcode, iQuant);
2933    
2934            if ((iMinSAD < 256) ||
2935                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2936                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2937                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
2938                    {
2939                            if (!MVzero(*currMV)) {
2940                                    iMinSAD += MV16_00_BIAS;
2941                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2942                                    iMinSAD -= MV16_00_BIAS;
2943                            }
2944                    }
2945    
2946          if (!(MotionFlags & PMV_HALFPEL8))                  if (MotionFlags & PMV_EARLYSTOP16)
2947          {                          goto PMVfastInt16_Terminate_with_Refine;
                 currMV->x = EVEN(currMV->x);  
                 currMV->y = EVEN(currMV->y);  
2948          }          }
2949    
         if (currMV->x > max_dx)  
                 currMV->x=max_dx;  
         if (currMV->x < min_dx)  
                 currMV->x=min_dx;  
         if (currMV->y > max_dy)  
                 currMV->y=max_dy;  
         if (currMV->y < min_dy)  
                 currMV->y=min_dy;  
2950    
2951  /***************** This is predictor SET A: only median prediction ******************/  /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2952       vector of the median.
2953       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2954    */
2955    
2956            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2957                    iFound = 2;
2958    
2959          iMinSAD = sad8( cur,  /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2960                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),     Otherwise select large Diamond Search.
2961                  iEdgedWidth);  */
         iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;  
2962    
2963            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2964                    iDiamondSize = 2;               // halfpel units!
2965            else
2966                    iDiamondSize = 4;               // halfpel units!
2967    
2968  // thresh1 is fixed to 256  /*
2969          if (iMinSAD < 256/4 )     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2970                  {     Also calculate (0,0) but do not subtract offset.
2971                          if (MotionFlags & PMV_QUICKSTOP8)     Let MinSAD be the smallest SAD up to this point.
2972                                  goto EPZS8_Terminate_without_Refine;     If MV is (0,0) subtract offset.
2973                          if (MotionFlags & PMV_EARLYSTOP8)  */
                                 goto EPZS8_Terminate_with_Refine;  
                 }  
2974    
2975  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  // (0,0) is often a good choice
2976    
2977  // previous frame MV          if (!MVzero(pmv[0]))
2978          CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);                  CHECK_MV16_ZERO;
2979    
2980  // MV=(0,0) is often a good choice  // previous frame MV is always possible
2981    
2982          CHECK_MV8_ZERO;          if (!MVzero(prevMB->i_mvs[0]))
2983                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2984                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2985    
2986  /* Terminate if MinSAD <= T_2  // left neighbour, if allowed
2987     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]  
2988            if (!MVzero(pmv[1]))
2989                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2990                            if (!MVequal(pmv[1], pmv[0]))
2991                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2992    
2993    // top neighbour, if allowed
2994            if (!MVzero(pmv[2]))
2995                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
2996                            if (!MVequal(pmv[2], pmv[0]))
2997                                    if (!MVequal(pmv[2], pmv[1]))
2998                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2999    
3000    // top right neighbour, if allowed
3001                                            if (!MVzero(pmv[3]))
3002                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
3003                                                            if (!MVequal(pmv[3], pmv[0]))
3004                                                                    if (!MVequal(pmv[3], pmv[1]))
3005                                                                            if (!MVequal(pmv[3], pmv[2]))
3006                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
3007                                                                                                                             pmv[3].y);
3008    
3009            if ((MVzero(*currMV)) &&
3010                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
3011                    iMinSAD -= MV16_00_BIAS;
3012    
3013    
3014    /* Step 6: If MinSAD <= thresa goto Step 10.
3015       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
3016  */  */
3017    
3018          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if ((iMinSAD <= threshA) ||
3019                  {                  (MVequal(*currMV, prevMB->i_mvs[0]) &&
3020                          if (MotionFlags & PMV_QUICKSTOP8)                   ((int32_t) iMinSAD < prevMB->i_sad16))) {
3021                                  goto EPZS8_Terminate_without_Refine;  
3022                          if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
3023                                  goto EPZS8_Terminate_with_Refine;                          goto PMVfastInt16_Terminate_with_Refine;
3024                  }                  }
3025    
 /************ (if Diamond Search)  **************/  
3026    
3027          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */  /************ (Diamond Search)  **************/
3028    /*
3029       Step 7: Perform Diamond search, with either the small or large diamond.
3030       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
3031       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
3032       If center then goto step 10.
3033       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
3034       Refine by using small diamond and goto step 10.
3035    */
3036    
3037          if (!(MotionFlags & PMV_HALFPELDIAMOND8))          if (MotionFlags & PMV_USESQUARES16)
3038                  iDiamondSize *= 2;                  MainSearchPtr = Square16_MainSearch;
3039            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
3040                    MainSearchPtr = AdvDiamond16_MainSearch;
3041            else
3042                    MainSearchPtr = Diamond16_MainSearch;
3043    
3044  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
3045    
 //      if (MotionFlags & PMV_USESQUARES8)  
 //              EPZSMainSearchPtr = Square8_MainSearch;  
 //      else  
                 EPZSMainSearchPtr = Diamond8_MainSearch;  
   
         iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,  
                 x, y,  
                 currMV->x, currMV->y, iMinSAD, &newMV,  
                 pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,  
                 iDiamondSize, iFcode, iQuant, 00);  
3046    
3047    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
3048            iSAD =
3049                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
3050                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
3051                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
3052                                                      iQuant, iFound);
3053    
3054          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
3055                  *currMV = newMV;                  *currMV = newMV;
3056                  iMinSAD = iSAD;                  iMinSAD = iSAD;
3057          }          }
3058    
3059          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH16) {
3060          {  /* extended: search (up to) two more times: orignal prediction and (0,0) */
 /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  
3061    
3062                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
3063                  {                          iSAD =
3064                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
3065                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
3066                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
3067                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, iFound);
3068    
3069                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
3070                                  *currMV = newMV;                                  *currMV = newMV;
3071                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
3072                          }                          }
3073                  }                  }
3074    
3075                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
3076                  {                          iSAD =
3077                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
3078                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
3079                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
3080                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, iFound);
3081    
3082                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
3083                                  *currMV = newMV;                                  *currMV = newMV;
3084                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
3085                          }                          }
3086                  }                  }
3087          }          }
3088    
3089  /***************        Choose best MV found     **************/  /*
3090       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
3091    */
3092    
3093  EPZS8_Terminate_with_Refine:  PMVfastInt16_Terminate_with_Refine:
         if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step  
                 iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,  
                                 x, y,  
                                 currMV, iMinSAD,  
                                 pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);  
3094    
3095  EPZS8_Terminate_without_Refine:          pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
3096            pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
3097    
3098          currPMV->x = currMV->x - pmv[0].x;          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
3099          currPMV->y = currMV->y - pmv[0].y;                  iMinSAD =
3100                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
3101                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
3102                                                             iFcode, iQuant, iEdgedWidth);
3103    
3104            pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
3105    
3106    PMVfastInt16_Terminate_without_Refine:
3107            currPMV->x = currMV->x - center_x;
3108            currPMV->y = currMV->y - center_y;
3109          return iMinSAD;          return iMinSAD;
3110  }  }
3111    
3112    
3113    
   
   
3114  /* ***********************************************************  /* ***********************************************************
3115          bvop motion estimation          bvop motion estimation
 // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)  
3116  ***************************************************************/  ***************************************************************/
3117    
3118  /*  void
3119  void MotionEstimationBVOP(  MotionEstimationBVOP(MBParam * const pParam,
                         MBParam * const pParam,  
3120                          FRAMEINFO * const frame,                          FRAMEINFO * const frame,
3121                                             const int32_t time_bp,
3122                                             const int32_t time_pp,
3123                          // forward (past) reference                          // forward (past) reference
3124                          const MACROBLOCK * const f_mbs,                          const MACROBLOCK * const f_mbs,
3125                      const IMAGE * const f_ref,                      const IMAGE * const f_ref,
# Line 1910  Line 3133 
3133                      const IMAGE * const b_refV,                      const IMAGE * const b_refV,
3134                          const IMAGE * const b_refHV)                          const IMAGE * const b_refHV)
3135  {  {
3136      const uint32_t mb_width = pParam->mb_width;          const int mb_width = pParam->mb_width;
3137      const uint32_t mb_height = pParam->mb_height;          const int mb_height = pParam->mb_height;
3138          const int32_t edged_width = pParam->edged_width;          const int edged_width = pParam->edged_width;
   
         int32_t i,j;  
   
         int32_t f_sad16;  
         int32_t b_sad16;  
         int32_t i_sad16;  
         int32_t d_sad16;  
         int32_t best_sad;  
3139    
3140            const int32_t iWidth = pParam->width;
3141            const int32_t iHeight = pParam->height;
3142    
3143            int i, j, k;
3144    
3145            static const VECTOR zeroMV={0,0};
3146    
3147            int f_sad16;    /* forward (as usual) search */
3148            int b_sad16;    /* backward (only in b-frames) search */
3149            int i_sad16;    /* interpolated (both direction, b-frames only) */
3150            int d_sad16;    /* direct mode (assume almost linear motion) */
3151    
3152            int best_sad;
3153    
3154            VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
3155            VECTOR f_interpolMV, b_interpolMV;
3156          VECTOR pmv_dontcare;          VECTOR pmv_dontcare;
3157    
3158            int min_dx, max_dx, min_dy, max_dy;
3159            int f_min_dx, f_max_dx, f_min_dy, f_max_dy;
3160            int b_min_dx, b_max_dx, b_min_dy, b_max_dy;
3161    
3162            int f_count=0;
3163            int b_count=0;
3164            int i_count=0;
3165            int d_count=0;
3166    
3167            const int64_t TRB = (int32_t)time_pp - (int32_t)time_bp;
3168        const int64_t TRD = (int32_t)time_pp;
3169    
3170            // fprintf(stderr,"TRB = %lld  TRD = %lld  time_bp =%d time_pp =%d\n\n",TRB,TRD,time_bp,time_pp);
3171          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
3172      for (j = 0; j < mb_height; j++)          for (j = 0; j < mb_height; j++) {
3173          {  
3174                  for (i = 0; i < mb_width; i++)                  f_predMV = zeroMV;      /* prediction is reset at left boundary */
3175                  {                  b_predMV = zeroMV;
3176    
3177                    for (i = 0; i < mb_width; i++) {
3178                          MACROBLOCK *mb = &frame->mbs[i + j*mb_width];                          MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
3179                          const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];                          const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
3180                          const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];                          const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
3181    
3182                          if (b_mb->mode == MODE_INTER                          mb->deltamv=zeroMV;
3183                                  && b_mb->cbp == 0  
3184                                  && b_mb->mvs[0].x == 0  /* special case, if collocated block is SKIPed: encoding is forward (0,0), cpb=0 without further ado */
3185                                  && b_mb->mvs[0].y == 0)  
3186                          {                          if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
3187                                  mb->mode = MB_IGNORE;                                  b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {
3188                                  mb->mvs[0].x = 0;                                  mb->mode = MODE_NOT_CODED;
3189                                  mb->mvs[0].y = 0;                                  mb->b_mvs[0] = mb->mvs[0] = zeroMV;
                                 mb->b_mvs[0].x = 0;  
                                 mb->b_mvs[0].y = 0;  
3190                                  continue;                                  continue;
3191                          }                          }
3192    
3193                            if (b_mb->mode == MODE_INTER4V)
3194                            {
3195                                    d_sad16 = 0;
3196                            /* same method of scaling as in decoder.c, so we copy from there */
3197                        for (k = 0; k < 4; k++) {
3198    
3199                                            mb->directmv[k] = b_mb->mvs[k];
3200    
3201                                            mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3202                        mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3203                                                                                    ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3204                                                : mb->mvs[k].x - mb->directmv[k].x);
3205    
3206                        mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3207                            mb->b_mvs[k].y = (int32_t) ((mb->deltamv.y == 0)
3208                                                                                    ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3209                                                : mb->mvs[k].y - mb->directmv[k].y);
3210    
3211                                            d_sad16 +=
3212                                                    sad8bi(frame->image.y + 2*(i+(k&1))*8 + 2*(j+(k>>1))*8*edged_width,
3213                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3214                                                                    2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->mvs[k], edged_width),
3215                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3216                                                                    2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->b_mvs[k], edged_width),
3217                                                      edged_width);
3218                                    }
3219                            }
3220                            else
3221                            {
3222                                    mb->directmv[3] = mb->directmv[2] = mb->directmv[1] =
3223                                            mb->directmv[0] = b_mb->mvs[0];
3224    
3225                                    mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3226                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3227                                                                            ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3228                                        : mb->mvs[0].x - mb->directmv[0].x);
3229    
3230                        mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3231                    mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
3232                                                                            ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3233                                        : mb->mvs[0].y - mb->directmv[0].y);
3234    
3235                                    d_sad16 = sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3236                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3237                                                                    i, j, 16, &mb->mvs[0], edged_width),
3238                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3239                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
3240                                                      edged_width);
3241    
3242                }
3243                        d_sad16 += calc_delta_16(mb->deltamv.x, mb->deltamv.y, 1, frame->quant);
3244    
3245                          // forward search                          // forward search
3246                          f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                          f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3247                                                  &frame->image,                                                  &frame->image, i, j,
3248                                                  i, j,                                                  mb->mvs[0].x, mb->mvs[0].y,                     /* start point f_directMV */
3249                                                  frame->motion_flags,  frame->quant, frame->fcode,                                                  f_predMV.x, f_predMV.y,                         /* center is f-prediction */
3250                                                  pParam,                                                  frame->motion_flags,
3251                                                  f_mbs,                                                  frame->quant, frame->fcode, pParam,
3252                                                  &mb->mvs[0], &pmv_dontcare);    // ignore pmv                                                  f_mbs, f_mbs,
3253                                                    &mb->mvs[0], &pmv_dontcare);
3254    
3255    
3256                          // backward search                          // backward search
3257                          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,
3258                                                  &frame->image,                                                  &frame->image, i, j,
3259                                                    mb->b_mvs[0].x, mb->b_mvs[0].y,         /* start point b_directMV */
3260                                                    b_predMV.x, b_predMV.y,                         /* center is b-prediction */
3261                                                    frame->motion_flags,
3262                                                    frame->quant, frame->bcode, pParam,
3263                                                    b_mbs, b_mbs,
3264                                                    &mb->b_mvs[0], &pmv_dontcare);
3265    
3266                            i_sad16 =
3267                                    sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3268                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3269                                                                    i, j, 16, &mb->mvs[0], edged_width),
3270                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3271                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
3272                                                      edged_width);
3273                        i_sad16 += calc_delta_16(mb->mvs[0].x-f_predMV.x, mb->mvs[0].y-f_predMV.y,
3274                                                                    frame->fcode, frame->quant);
3275                        i_sad16 += calc_delta_16(mb->b_mvs[0].x-b_predMV.x, mb->b_mvs[0].y-b_predMV.y,
3276                                                                    frame->bcode, frame->quant);
3277    
3278                            get_range(&f_min_dx, &f_max_dx, &f_min_dy, &f_max_dy, i, j, 16, iWidth, iHeight,
3279                              frame->fcode);
3280                            get_range(&b_min_dx, &b_max_dx, &b_min_dy, &b_max_dy, i, j, 16, iWidth, iHeight,
3281                              frame->bcode);
3282    
3283    /* Interpolated MC motion vector search, this is tedious and more complicated because there are
3284       two values for everything, always one for backward and one for forward ME. Still, we don't gain
3285       much from this search, maybe it should simply be skipped and simply current i_sad16 value used
3286       as "optimal". */
3287    
3288                            i_sad16 = Diamond16_InterpolMainSearch(
3289                                                    f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3290                                                    frame->image.y + i * 16 + j * 16 * edged_width,
3291                                                    b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3292                                                  i, j,                                                  i, j,
3293                                                  frame->motion_flags,  frame->quant, frame->bcode,                                                  mb->mvs[0].x, mb->mvs[0].y,
3294                                                  pParam,                                                  mb->b_mvs[0].x, mb->b_mvs[0].y,
3295                                                  b_mbs,                                                  i_sad16,
3296                                                  &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv                                                  &f_interpolMV, &b_interpolMV,
3297                                                    f_predMV.x, f_predMV.y, b_predMV.x, b_predMV.y,
3298                                                    f_min_dx, f_max_dx, f_min_dy, f_max_dy,
3299                                                    b_min_dx, b_max_dx, b_min_dy, b_max_dy,
3300                                                    edged_width,  2,
3301                                                    frame->fcode, frame->bcode,frame->quant,0);
3302    
3303                          // interpolate search (simple, but effective)                          i_sad16 = Diamond16_InterpolMainSearch(
3304                          i_sad16 = sad16bi_c(                                                  f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3305                                          frame->image.y + i*16 + j*16*edged_width,                                          frame->image.y + i*16 + j*16*edged_width,
3306                                          get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                                  b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3307                                                  i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),                                                  i, j,
3308                                          get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                                                  f_interpolMV.x, f_interpolMV.y,
3309                                                  i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),                                                  b_interpolMV.x, b_interpolMV.y,
3310                                          edged_width);                                                  i_sad16,
3311                                                    &f_interpolMV, &b_interpolMV,
3312                                                    f_predMV.x, f_predMV.y, b_predMV.x, b_predMV.y,
3313                                                    f_min_dx, f_max_dx, f_min_dy, f_max_dy,
3314                                                    b_min_dx, b_max_dx, b_min_dy, b_max_dy,
3315                                                    edged_width,  1,
3316                                                    frame->fcode, frame->bcode,frame->quant,0);             // equiv to halfpel refine
3317    
3318    
3319    /*  DIRECT MODE DELTA VECTOR SEARCH.
3320        This has to be made more effective, but at the moment I'm happy it's running at all */
3321    
3322    /* There are two range restrictions for direct mode: deltaMV is limited to [-32,31] in halfpel units, and
3323       absolute vector must not lie outside of image dimensions. Constraint one is dealt with by CHECK_MV16_DIRECT
3324       and for constraint two we need distance to boundary. This is done by get_range very large fcode (hack!) */
3325    
3326                          // TODO: direct search                          get_range(&min_dx, &max_dx, &min_dy, &max_dy, i, j, 16, iWidth, iHeight, 19);
                         // predictor + range of [-32,32]  
                         d_sad16 = 65535;  
3327    
3328                            d_sad16 = Diamond16_DirectMainSearch(
3329                                                    f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3330                                                    frame->image.y + i*16 + j*16*edged_width,
3331                                                    b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3332                                                    i, j,
3333                                                    TRB,TRD,
3334                                                    0,0,
3335                                                    d_sad16,
3336                                                    &mb->deltamv,
3337                                                    mb->directmv, // this has to be pre-initialized with b_mb->mvs[]
3338                                            min_dx, max_dx, min_dy, max_dy,
3339                                                    edged_width, 2, frame->quant, 0);
3340    
3341                          if (f_sad16 < b_sad16)                          d_sad16 = Diamond16_DirectMainSearch(
3342                          {                                                  f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3343                                                    frame->image.y + i*16 + j*16*edged_width,
3344                                                    b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3345                                                    i, j,
3346                                                    TRB,TRD,
3347                                                    mb->deltamv.x, mb->deltamv.y,
3348                                                    d_sad16,
3349                                                    &mb->deltamv,
3350                                                    mb->directmv, // this has to be pre-initialized with b_mb->mvs[]
3351                                            min_dx, max_dx, min_dy, max_dy,
3352                                                    edged_width, 1, frame->quant, 0);               // equiv to halfpel refine
3353    
3354    
3355    //                      i_sad16 = 65535;                /* remove the comment to disable any of the MODEs */
3356    //                      f_sad16 = 65535;
3357    //                      b_sad16 = 65535;
3358    //                      d_sad16 = 65535;
3359    
3360                            if (f_sad16 < b_sad16) {
3361                                  best_sad = f_sad16;                                  best_sad = f_sad16;
3362                                  mb->mode = MB_FORWARD;                                  mb->mode = MODE_FORWARD;
3363                          }                          } else {
                         else  
                         {  
3364                                  best_sad = b_sad16;                                  best_sad = b_sad16;
3365                                  mb->mode = MB_BACKWARD;                                  mb->mode = MODE_BACKWARD;
3366                          }                          }
3367    
3368                          if (i_sad16 < best_sad)                          if (i_sad16 < best_sad) {
                         {  
3369                                  best_sad = i_sad16;                                  best_sad = i_sad16;
3370                                  mb->mode = MB_INTERPOLATE;                                  mb->mode = MODE_INTERPOLATE;
3371                          }                          }
3372    
3373                          if (d_sad16 < best_sad)                          if (d_sad16 < best_sad) {
3374    
3375                                    if (b_mb->mode == MODE_INTER4V)
3376                                    {
3377    
3378                                    /* how to calc vectors is defined in standard. mvs[] and b_mvs[] are only for motion compensation */
3379                                    /* for the bitstream, the value mb->deltamv is read directly */
3380    
3381                                for (k = 0; k < 4; k++) {
3382    
3383                                                    mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3384                                mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3385                                                                                            ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3386                                                        : mb->mvs[k].x - mb->directmv[k].x);
3387    
3388                                mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3389                            mb->b_mvs[k].y = (int32_t) ((mb->deltamv.y == 0)
3390                                                                                            ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3391                                                : mb->mvs[k].y - mb->directmv[k].y);
3392                                            }
3393                                    }
3394                                    else
3395                          {                          {
3396                                            mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3397    
3398                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3399                                                                                    ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3400                                            : mb->mvs[0].x - mb->directmv[0].x);
3401    
3402                                mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3403    
3404                            mb->b_mvs[0].y = (int32_t) ((mb->deltamv.y == 0)
3405                                                                                    ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3406                                                : mb->mvs[0].y - mb->directmv[0].y);
3407    
3408                                            mb->mvs[3] = mb->mvs[2] = mb->mvs[1] = mb->mvs[0];
3409                                            mb->b_mvs[3] = mb->b_mvs[2] = mb->b_mvs[1] = mb->b_mvs[0];
3410                    }
3411    
3412                                  best_sad = d_sad16;                                  best_sad = d_sad16;
3413                                  mb->mode = MB_DIRECT;                                  mb->mode = MODE_DIRECT;
3414                          }                          }
3415    
3416                            switch (mb->mode)
3417                            {
3418                                    case MODE_FORWARD:
3419                                            f_count++;
3420                                            f_predMV = mb->mvs[0];
3421                                            break;
3422                                    case MODE_BACKWARD:
3423                                            b_count++;
3424                                            b_predMV = mb->b_mvs[0];
3425    
3426                                            break;
3427                                    case MODE_INTERPOLATE:
3428                                            i_count++;
3429                                            mb->mvs[0] = f_interpolMV;
3430                                            mb->b_mvs[0] = b_interpolMV;
3431                                            f_predMV = mb->mvs[0];
3432                                            b_predMV = mb->b_mvs[0];
3433                                            break;
3434                                    case MODE_DIRECT:
3435                                            d_count++;
3436                                            break;
3437                                    default:
3438                                            break;
3439                  }                  }
3440    
3441          }          }
3442  }  }
3443    
 */  
3444    #ifdef _DEBUG_BFRAME_STAT
3445            fprintf(stderr,"B-Stat: F: %04d   B: %04d   I: %04d  D: %04d\n",
3446                                    f_count,b_count,i_count,d_count);
3447    #endif
3448    
3449    }

Legend:
Removed from v.118  
changed lines
  Added in v.348

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