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

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

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

revision 140, Thu Apr 25 21:32:05 2002 UTC revision 341, Thu Jul 25 00:43:19 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   *      25.04.2002 partial prevMB conversion
37   *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>   *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>
38   *  14.04.2002 added MotionEstimationBVOP()   *  14.04.2002 added MotionEstimationBVOP()
# Line 46  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)  
 #define MV8_00_BIAS     (0)  
   
 /* 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 uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
 int32_t EPZSSearch16(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
   
 int32_t PMVfastSearch8(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const int start_x, const int start_y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
 int32_t EPZSSearch8(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const int start_x, const int start_y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
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 193  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 201  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 219  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                              const int32_t dy,
141                              const uint32_t iFcode,
142                              const uint32_t iQuant)
143  {  {
144          return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));          return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) +
145                                                                                                              mv_bits(dy, iFcode));
146  }  }
147    
148  static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)  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  {  {
154      return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));          return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) +
155                                                                                                       mv_bits(dy, iFcode));
156  }  }
157    
158    bool
159    MotionEstimation(MBParam * const pParam,
   
   
 #ifndef SEARCH16  
 #define SEARCH16        PMVfastSearch16  
 //#define SEARCH16      FullSearch16  
 //#define SEARCH16      EPZSSearch16  
 #endif  
   
 #ifndef SEARCH8  
 #define SEARCH8         PMVfastSearch8  
 //#define SEARCH8       EPZSSearch8  
 #endif  
   
 bool MotionEstimation(  
         MBParam * const pParam,  
160          FRAMEINFO * const current,          FRAMEINFO * const current,
161          FRAMEINFO * const reference,          FRAMEINFO * const reference,
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,
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 * pMBs = current->mbs;          MACROBLOCK *const pMBs = current->mbs;
170          IMAGE * pCurrent = &current->image;          MACROBLOCK *const prevMBs = reference->mbs;
171            const IMAGE *const pCurrent = &current->image;
172          MACROBLOCK * prevMBs = reference->mbs;  // previous frame          const IMAGE *const pRef = &reference->image;
173          IMAGE * pRef = &reference->image;  
174            static const VECTOR zeroMV = { 0, 0 };
175            VECTOR predMV;
176          uint32_t i, j, iIntra = 0;  
177            int32_t x, y;
178          VECTOR mv16;          int32_t iIntra = 0;
179          VECTOR pmv16;          VECTOR pmv;
   
         int32_t sad8 = 0;  
         int32_t sad16;  
         int32_t deviation;  
180    
181          if (sadInit)          if (sadInit)
182                  (*sadInit)();                  (*sadInit)();
183    
184            for (y = 0; y < iHcount; y++)   {
185                    for (x = 0; x < iWcount; x ++)  {
186    
187          /* eventhough we have a seperate prevMBs,                          MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
            pmvfast/epsz does something "funny" with the previous frames data */  
   
 /*      for (i = 0; i < iHcount; i++)  
                 for (j = 0; j < iWcount; j++)  
                 {  
                         pMBs[j + i * iWcount].mvs[0] = prevMBs[j + i * iWcount].mvs[0];  
                         pMBs[j + i * iWcount].mvs[1] = prevMBs[j + i * iWcount].mvs[1];  
                         pMBs[j + i * iWcount].mvs[2] = prevMBs[j + i * iWcount].mvs[2];  
                         pMBs[j + i * iWcount].mvs[3] = prevMBs[j + i * iWcount].mvs[3];  
                 }  
 */  
         /*dprintf("*** BEFORE ***");  
         for (i = 0; i < iHcount; i++)  
                 for (j = 0; j < iWcount; j++)  
                 {  
                         dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,  
                                 pMBs[j + i * iWcount].mode,  
                                 pMBs[j + i * iWcount].dquant,  
                                 pMBs[j + i * iWcount].mvs[0],  
                                 pMBs[j + i * iWcount].mvs[1],  
                                 pMBs[j + i * iWcount].mvs[2],  
                                 pMBs[j + i * iWcount].mvs[3],  
                                 prevMBs[j + i * iWcount].sad8[0],  
                                 prevMBs[j + i * iWcount].sad8[1],  
                                 prevMBs[j + i * iWcount].sad8[2],  
                                 prevMBs[j + i * iWcount].sad8[3],  
                                 prevMBs[j + i * iWcount].sad16);  
                 }  
         */  
   
         // note: i==horizontal, j==vertical  
         for (i = 0; i < iHcount; i++)  
                 for (j = 0; j < iWcount; j++)  
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
                         MACROBLOCK *prevMB = &prevMBs[j + i * iWcount];  
188    
189                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
                                          j, i, current->motion_flags, current->quant, current->fcode,  
                                          pParam, pMBs, prevMBs, &mv16, &pmv16);  
                         pMB->sad16=sad16;  
190    
191                            pMB->sad16 =
192                                    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                          /* decide: MODE_INTER or MODE_INTRA                          if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
199                             if (dev_intra < sad_inter - 2 * nb) use_intra                                  int32_t deviation;
                         */  
200    
201                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                                  deviation =
202                                            dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
203                                                      pParam->edged_width);
204    
205                          if (deviation < (sad16 - INTER_BIAS))                                  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[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
211    
212                                  iIntra++;                                  iIntra++;
213                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 341  Line 215 
215    
216                                  continue;                                  continue;
217                          }                          }
218                            }
219    
220                            pmv = pMB->pmvs[0];
221                          if (current->global_flags & XVID_INTER4V)                          if (current->global_flags & XVID_INTER4V)
222                          {                                  if ((!(current->global_flags & XVID_LUMIMASKING) ||
223                                  pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                           pMB->dquant == NO_CHANGE)) {
224                                                         2 * j, 2 * i, mv16.x, mv16.y,                                          int32_t sad8 = IMV16X16 * current->quant;
225                                                             current->motion_flags, current->quant, current->fcode,  
226                                                         pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);                                          if (sad8 < pMB->sad16) {
227                                                    sad8 += pMB->sad8[0] =
228                                  pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
229                                                         2 * j + 1, 2 * i, mv16.x, mv16.y,                                                                          pCurrent, 2 * x, 2 * y,
230                                                             current->motion_flags, current->quant, current->fcode,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
231                                                         pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);                                                                          current->motion_flags,
232                                                                            current->quant, current->fcode, pParam,
233                                  pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                                          pMBs, prevMBs, &pMB->mvs[0],
234                                                         2 * j, 2 * i + 1, mv16.x, mv16.y,                                                                          &pMB->pmvs[0]);
235                                                             current->motion_flags, current->quant, current->fcode,                                          }
236                                                         pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);                                          if (sad8 < pMB->sad16) {
237    
238                                  pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                  predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
239                                                         2 * j + 1, 2 * i + 1, mv16.x, mv16.y,                                                  sad8 += pMB->sad8[1] =
240                                                             current->motion_flags, current->quant, current->fcode,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
241                                                         pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);                                                                          pCurrent, 2 * x + 1, 2 * y,
242                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
243                                  sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];                                                                          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 (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE)                                          if (sad8 < pMB->sad16) {
                         {  
                                 if (((current->global_flags & XVID_INTER4V)==0) ||  
                                     (sad16 < (sad8 + (int32_t)(IMV16X16 * current->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  
                         {  
                                 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;  
                         }  
285                  }                  }
286    
287  /*      dprintf("*** AFTER ***", pMBs[0].b_mvs[0].x);                          pMB->mode = MODE_INTER;
288          for (i = 0; i < iHcount; i++)                          pMB->pmvs[0] = pmv;     /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
289                  for (j = 0; j < iWcount; j++)                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
290                  {                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
291                          dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,                                  pMB->sad16;
292                                  pMBs[j + i * iWcount].mode,                          }
                                 pMBs[j + i * iWcount].dquant,  
                                 pMBs[j + i * iWcount].mvs[0],  
                                 pMBs[j + i * iWcount].mvs[1],  
                                 pMBs[j + i * iWcount].mvs[2],  
                                 pMBs[j + i * iWcount].mvs[3],  
                                 pMBs[j + i * iWcount].sad8[0],  
                                 pMBs[j + i * iWcount].sad8[1],  
                                 pMBs[j + i * iWcount].sad8[2],  
                                 pMBs[j + i * iWcount].sad8[3],  
                                 pMBs[j + i * iWcount].sad16);  
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);\
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 448  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 458  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 468  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 476  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 484  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 494  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 504  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 514  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 540  Line 410 
410          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
411          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
412          int32_t iSAD;          int32_t iSAD;
413          int32_t pred_x,pred_y;          VECTOR pred;
414    
415    
416          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
417    
418          iSAD = sad16( cur,          iSAD = sad16( cur,
419                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
# Line 552  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 584  Line 460 
460          int32_t iDirection=0;          int32_t iDirection=0;
461          int32_t iSAD;          int32_t iSAD;
462          VECTOR backupMV;          VECTOR backupMV;
463          backupMV.x = startx;  
464          backupMV.y = starty;          backupMV.x = start_x;
465            backupMV.y = start_y;
466    
467  /* 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 */
468    
# Line 595  Line 472 
472          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
473    
474          if (iDirection)          if (iDirection)
475                  while (!iFound)                  while (!iFound) {
                 {  
476                          iFound = 1;                          iFound = 1;
477                          backupMV=*currMV;                          backupMV=*currMV;
478    
479                          if ( iDirection != 2)                          if ( iDirection != 2)
480                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
481                                                                                       backupMV.y, 1);
482                          if ( iDirection != 1)                          if ( iDirection != 1)
483                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
484                                                                                       backupMV.y, 2);
485                          if ( iDirection != 4)                          if ( iDirection != 4)
486                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
487                                                                                       backupMV.y - iDiamondSize, 3);
488                          if ( iDirection != 3)                          if ( iDirection != 3)
489                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
490                  }                                                                                     backupMV.y + iDiamondSize, 4);
491          else          } else {
492          {                  currMV->x = start_x;
493                  currMV->x = startx;                  currMV->y = start_y;
                 currMV->y = starty;  
494          }          }
495          return iMinSAD;          return iMinSAD;
496  }  }
497    
498  int32_t Square16_MainSearch(  int32_t
499                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
500                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
501                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
502                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
503                                          const uint8_t * const cur,                                          const uint8_t * const cur,
504                                          const int x, const int y,                                          const int x,
505                                          int32_t startx, int32_t starty,                                          const int y,
506                                          int32_t iMinSAD,                                     const int start_x,
507                                       const int start_y,
508                                       int iMinSAD,
509                                          VECTOR * const currMV,                                          VECTOR * const currMV,
510                                          const VECTOR * const pmv,                                     const int center_x,
511                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
512                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
513                                            const int32_t max_dx,
514                                            const int32_t min_dy,
515                                            const int32_t max_dy,
516                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
517                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
518                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 641  Line 524 
524          int32_t iDirection=0;          int32_t iDirection=0;
525          int32_t iSAD;          int32_t iSAD;
526          VECTOR backupMV;          VECTOR backupMV;
527          backupMV.x = startx;  
528          backupMV.y = starty;          backupMV.x = start_x;
529            backupMV.y = start_y;
530    
531  /* 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 */
532    
# Line 657  Line 541 
541          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
542          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
543    
544          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
545          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
546          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
547          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
548            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
549                                                             backupMV.y - iDiamondSize, 7);
550            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
551                                                             backupMV.y + iDiamondSize, 8);
552    
553    
554          if (iDirection)          if (iDirection)
555                  while (!iFound)                  while (!iFound) {
                 {  
556                          iFound = 1;                          iFound = 1;
557                          backupMV=*currMV;                          backupMV=*currMV;
558    
559                          switch (iDirection)                          switch (iDirection) {
                         {  
560                                  case 1:                                  case 1:
561                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
562                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
563                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
564                                                                                     backupMV.y - iDiamondSize, 5);
565                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
566                                                                                     backupMV.y - iDiamondSize, 7);
567                                          break;                                          break;
568                                  case 2:                                  case 2:
569                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
570                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
571                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
572                                                                                     backupMV.y + iDiamondSize, 6);
573                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
574                                                                                     backupMV.y + iDiamondSize, 8);
575                                          break;                                          break;
576    
577                                  case 3:                                  case 3:
578                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
579                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
580                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
581                                                                                     backupMV.y - iDiamondSize, 7);
582                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
583                                                                                     backupMV.y + iDiamondSize, 8);
584                                          break;                                          break;
585    
586                                  case 4:                                  case 4:
587                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
588                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
589                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
590                                                                                     backupMV.y - iDiamondSize, 5);
591                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
592                                                                                     backupMV.y + iDiamondSize, 6);
593                                          break;                                          break;
594    
595                                  case 5:                                  case 5:
596                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,
597                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
598                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
599                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
600                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
601                                                                                     backupMV.y - iDiamondSize, 5);
602                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
603                                                                                     backupMV.y + iDiamondSize, 6);
604                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
605                                                                                     backupMV.y - iDiamondSize, 7);
606                                          break;                                          break;
607    
608                                  case 6:                                  case 6:
609                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
610                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
611                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
612                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
613                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
614                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
615                                                                                     backupMV.y - iDiamondSize, 5);
616                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
617                                                                                     backupMV.y + iDiamondSize, 6);
618                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
619                                                                                     backupMV.y + iDiamondSize, 8);
620    
621                                          break;                                          break;
622    
623                                  case 7:                                  case 7:
624                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
625                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
626                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
627                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
628                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
629                                                                                     backupMV.y - iDiamondSize, 5);
630                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
631                                                                                     backupMV.y - iDiamondSize, 7);
632                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
633                                                                                     backupMV.y + iDiamondSize, 8);
634                                          break;                                          break;
635    
636                                  case 8:                                  case 8:
637                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
638                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
639                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
640                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
641                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
642                                                                                     backupMV.y + iDiamondSize, 6);
643                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
644                                                                                     backupMV.y - iDiamondSize, 7);
645                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
646                                                                                     backupMV.y + iDiamondSize, 8);
647                                          break;                                          break;
648                          default:                          default:
649                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,
650                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
651                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
652                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
653                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
654                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
655                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
656                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
657                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
658                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
659                                                                                     backupMV.y - iDiamondSize, 5);
660                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
661                                                                                     backupMV.y + iDiamondSize, 6);
662                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
663                                                                                     backupMV.y - iDiamondSize, 7);
664                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
665                                                                                     backupMV.y + iDiamondSize, 8);
666                                          break;                                          break;
667                          }                          }
668                  }          } else {
669          else                  currMV->x = start_x;
670                  {                  currMV->y = start_y;
                         currMV->x = startx;  
                         currMV->y = starty;  
671                  }                  }
672          return iMinSAD;          return iMinSAD;
673  }  }
674    
675    
676  int32_t Full16_MainSearch(  int32_t
677                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
678                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
679                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
680                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
681                                          const uint8_t * const cur,                                          const uint8_t * const cur,
682                                          const int x, const int y,                                    const int x,
683                                          int32_t startx, int32_t starty,                                    const int y,
684                                          int32_t iMinSAD,                                     const int start_x,
685                                       const int start_y,
686                                       int iMinSAD,
687                                          VECTOR * const currMV,                                          VECTOR * const currMV,
688                                          const VECTOR * const pmv,                                     const int center_x,
689                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
690                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
691                                      const int32_t max_dx,
692                                      const int32_t min_dy,
693                                      const int32_t max_dy,
694                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
695                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
696                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 771  Line 700 
700          int32_t iSAD;          int32_t iSAD;
701          int32_t dx,dy;          int32_t dx,dy;
702          VECTOR backupMV;          VECTOR backupMV;
703          backupMV.x = startx;  
704          backupMV.y = starty;          backupMV.x = start_x;
705            backupMV.y = start_y;
706    
707          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
708                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 781  Line 711 
711          return iMinSAD;          return iMinSAD;
712  }  }
713    
714  int32_t Full8_MainSearch(  int32_t
715                                          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
716                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
717                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
718                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
719                                          const uint8_t * const cur,                                          const uint8_t * const cur,
720                                          const int x, const int y,                                                  const int x,
721                                          int32_t startx, int32_t starty,                                                  const int y,
722                                          int32_t iMinSAD,                                             int start_x,
723                                               int start_y,
724                                               int iMinSAD,
725                                          VECTOR * const currMV,                                          VECTOR * const currMV,
726                                          const VECTOR * const pmv,                                             const int center_x,
727                                          const int32_t min_dx, const int32_t max_dx,                                             const int center_y,
728                                          const int32_t min_dy, const int32_t max_dy,                                                  const int32_t min_dx,
729                                                    const int32_t max_dx,
730                                                    const int32_t min_dy,
731                                                    const int32_t max_dy,
732                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
733                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
734                                          const int32_t iFcode,                                          const int32_t iFcode,
735                                          const int32_t iQuant,                                          const int32_t iQuant,
736                                          int iFound)                                                  int iDirection)
737  {  {
738    
739          int32_t iSAD;          int32_t iSAD;
         int32_t dx,dy;  
         VECTOR backupMV;  
         backupMV.x = startx;  
         backupMV.y = starty;  
740    
741          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);  
742    
743          return iMinSAD;          if (iDirection) {
744  }                  CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
745                    CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
746                    CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
747                    CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
748            } else {
749                    int bDirection = 1 + 2 + 4 + 8;
750    
751                    do {
752                            iDirection = 0;
753                            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)
754                                    CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
755    
756                            if (bDirection & 2)
757                                    CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
758    
759  int32_t Halfpel16_Refine(                          if (bDirection & 4)
760          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) */  
761    
762          int32_t iSAD;                          if (bDirection & 8)
763          VECTOR backupMV = *currMV;                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
764    
765          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);  
766    
767          return iMinSAD;                          if (iDirection)         //checking if anything found
768                            {
769                                    bDirection = iDirection;
770                                    iDirection = 0;
771                                    start_x = currMV->x;
772                                    start_y = currMV->y;
773                                    if (bDirection & 3)     //our candidate is left or right
774                                    {
775                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
776                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
777                                    } else                  // what remains here is up or down
778                                    {
779                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
780                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
781  }  }
782    
783  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)                                  if (iDirection) {
784                                            bDirection += iDirection;
785                                            start_x = currMV->x;
786  int32_t PMVfastSearch16(                                          start_y = currMV->y;
787                                          const uint8_t * const pRef,                                  }
788                                          const uint8_t * const pRefH,                          } else                          //about to quit, eh? not so fast....
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV)  
789  {  {
790      const uint32_t iWcount = pParam->mb_width;                                  switch (bDirection) {
791          const int32_t iWidth = pParam->width;                                  case 2:
792          const int32_t iHeight = pParam->height;                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
793          const int32_t iEdgedWidth = pParam->edged_width;                                                                                           start_y - iDiamondSize, 2 + 4);
794                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
795                                                                                             start_y + iDiamondSize, 2 + 8);
796                                            break;
797                                    case 1:
798    
799          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
800                                                                                             start_y - iDiamondSize, 1 + 4);
801                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
802                                                                                             start_y + iDiamondSize, 1 + 8);
803                                            break;
804                                    case 2 + 4:
805                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
806                                                                                             start_y - iDiamondSize, 1 + 4);
807                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
808                                                                                             start_y - iDiamondSize, 2 + 4);
809                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
810                                                                                             start_y + iDiamondSize, 2 + 8);
811                                            break;
812                                    case 4:
813                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
814                                                                                             start_y - iDiamondSize, 2 + 4);
815                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
816                                                                                             start_y - iDiamondSize, 1 + 4);
817                                            break;
818                                    case 8:
819                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
820                                                                                             start_y + iDiamondSize, 2 + 8);
821                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
822                                                                                             start_y + iDiamondSize, 1 + 8);
823                                            break;
824                                    case 1 + 4:
825                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
826                                                                                             start_y + iDiamondSize, 1 + 8);
827                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
828                                                                                             start_y - iDiamondSize, 1 + 4);
829                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
830                                                                                             start_y - iDiamondSize, 2 + 4);
831                                            break;
832                                    case 2 + 8:
833                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
834                                                                                             start_y - iDiamondSize, 1 + 4);
835                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
836                                                                                             start_y + iDiamondSize, 1 + 8);
837                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
838                                                                                             start_y + iDiamondSize, 2 + 8);
839                                            break;
840                                    case 1 + 8:
841                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
842                                                                                             start_y - iDiamondSize, 2 + 4);
843                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
844                                                                                             start_y + iDiamondSize, 2 + 8);
845                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
846                                                                                             start_y + iDiamondSize, 1 + 8);
847                                            break;
848                                    default:                //1+2+4+8 == we didn't find anything at all
849                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
850                                                                                             start_y - iDiamondSize, 1 + 4);
851                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
852                                                                                             start_y + iDiamondSize, 1 + 8);
853                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
854                                                                                             start_y - iDiamondSize, 2 + 4);
855                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
856                                                                                             start_y + iDiamondSize, 2 + 8);
857                                            break;
858                                    }
859                                    if (!iDirection)
860                                            break;          //ok, the end. really
861                                    else {
862                                            bDirection = iDirection;
863                                            start_x = currMV->x;
864                                            start_y = currMV->y;
865                                    }
866                            }
867                    }
868                    while (1);                              //forever
869            }
870            return iMinSAD;
871    }
872    
873    
874    #define CHECK_MV16_F_INTERPOL(X,Y,BX,BY) { \
875      if ( ((X) <= max_dx) && ((X) >= min_dx) \
876        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
877      { \
878        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
879        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
880        if (iSAD < iMinSAD) \
881        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
882    }
883    
884    #define CHECK_MV16_F_INTERPOL_DIR(X,Y,BX,BY,D) { \
885      if ( ((X) <= max_dx) && ((X) >= min_dx) \
886        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
887      { \
888        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
889        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
890        if (iSAD < iMinSAD) \
891        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
892    }
893    
894    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y,BX,BY,D) { \
895      if ( ((X) <= max_dx) && ((X) >= min_dx) \
896        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
897      { \
898        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
899        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
900        if (iSAD < iMinSAD) \
901        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
902    }
903    
904    
905    #define CHECK_MV16_B_INTERPOL(FX,FY,X,Y) { \
906      if ( ((X) <= max_dx) && ((X) >= min_dx) \
907        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
908      { \
909        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
910        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
911        if (iSAD < iMinSAD) \
912        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
913    }
914    
915    
916    #define CHECK_MV16_B_INTERPOL_DIR(FX,FY,X,Y,D) { \
917      if ( ((X) <= max_dx) && ((X) >= min_dx) \
918        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
919      { \
920        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
921        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
922        if (iSAD < iMinSAD) \
923        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
924    }
925    
926    
927    #define CHECK_MV16_B_INTERPOL_FOUND(FX,FY,X,Y,D) { \
928      if ( ((X) <= max_dx) && ((X) >= min_dx) \
929        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
930      { \
931        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
932        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
933        if (iSAD < iMinSAD) \
934        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
935    }
936    
937    
938    #if (0==1)
939    int32_t
940    Diamond16_InterpolMainSearch(
941                                            const uint8_t * const f_pRef,
942                                             const uint8_t * const f_pRefH,
943                                             const uint8_t * const f_pRefV,
944                                             const uint8_t * const f_pRefHV,
945                                             const uint8_t * const cur,
946    
947                                            const uint8_t * const b_pRef,
948                                             const uint8_t * const b_pRefH,
949                                             const uint8_t * const b_pRefV,
950                                             const uint8_t * const b_pRefHV,
951    
952                                             const int x,
953                                             const int y,
954    
955                                       const int f_start_x,
956                                       const int f_start_y,
957                                       const int b_start_x,
958                                       const int b_start_y,
959    
960                                       int iMinSAD,
961                                       VECTOR * const f_currMV,
962                                       VECTOR * const b_currMV,
963    
964                                       const int f_center_x,
965                                       const int f_center_y,
966                                       const int b_center_x,
967                                       const int b_center_y,
968    
969                                             const int32_t min_dx,
970                                             const int32_t max_dx,
971                                             const int32_t min_dy,
972                                             const int32_t max_dy,
973                                             const int32_t iEdgedWidth,
974                                             const int32_t iDiamondSize,
975    
976                                             const int32_t f_iFcode,
977                                             const int32_t b_iFcode,
978    
979                                             const int32_t iQuant,
980                                             int iFound)
981    {
982    /* Do a diamond search around given starting point, return SAD of best */
983    
984            int32_t f_iDirection = 0;
985            int32_t b_iDirection = 0;
986            int32_t iSAD;
987    
988            VECTOR f_backupMV;
989            VECTOR b_backupMV;
990    
991            f_backupMV.x = start_x;
992            f_backupMV.y = start_y;
993            b_backupMV.x = start_x;
994            b_backupMV.y = start_y;
995    
996    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
997    
998            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
999            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1000            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1001            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1002    
1003            if (iDirection)
1004                    while (!iFound) {
1005                            iFound = 1;
1006                            backupMV = *currMV;
1007    
1008                            if (iDirection != 2)
1009                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1010                                                                                       backupMV.y, 1);
1011                            if (iDirection != 1)
1012                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1013                                                                                       backupMV.y, 2);
1014                            if (iDirection != 4)
1015                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1016                                                                                       backupMV.y - iDiamondSize, 3);
1017                            if (iDirection != 3)
1018                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1019                                                                                       backupMV.y + iDiamondSize, 4);
1020            } else {
1021                    currMV->x = start_x;
1022                    currMV->y = start_y;
1023            }
1024            return iMinSAD;
1025    }
1026    #endif
1027    
1028    
1029    int32_t
1030    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1031                                               const uint8_t * const pRefH,
1032                                               const uint8_t * const pRefV,
1033                                               const uint8_t * const pRefHV,
1034                                               const uint8_t * const cur,
1035                                               const int x,
1036                                               const int y,
1037                                               int start_x,
1038                                               int start_y,
1039                                               int iMinSAD,
1040                                               VECTOR * const currMV,
1041                                               const int center_x,
1042                                               const int center_y,
1043                                               const int32_t min_dx,
1044                                               const int32_t max_dx,
1045                                               const int32_t min_dy,
1046                                               const int32_t max_dy,
1047                                               const int32_t iEdgedWidth,
1048                                               const int32_t iDiamondSize,
1049                                               const int32_t iFcode,
1050                                               const int32_t iQuant,
1051                                               int iDirection)
1052    {
1053    
1054            int32_t iSAD;
1055    
1056    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1057    
1058            if (iDirection) {
1059                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1060                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1061                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1062                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1063            } else {
1064                    int bDirection = 1 + 2 + 4 + 8;
1065    
1066                    do {
1067                            iDirection = 0;
1068                            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)
1069                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1070    
1071                            if (bDirection & 2)
1072                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1073    
1074                            if (bDirection & 4)
1075                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1076    
1077                            if (bDirection & 8)
1078                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1079    
1080                            /* now we're doing diagonal checks near our candidate */
1081    
1082                            if (iDirection)         //checking if anything found
1083                            {
1084                                    bDirection = iDirection;
1085                                    iDirection = 0;
1086                                    start_x = currMV->x;
1087                                    start_y = currMV->y;
1088                                    if (bDirection & 3)     //our candidate is left or right
1089                                    {
1090                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1091                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1092                                    } else                  // what remains here is up or down
1093                                    {
1094                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1095                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1096                                    }
1097    
1098                                    if (iDirection) {
1099                                            bDirection += iDirection;
1100                                            start_x = currMV->x;
1101                                            start_y = currMV->y;
1102                                    }
1103                            } else                          //about to quit, eh? not so fast....
1104                            {
1105                                    switch (bDirection) {
1106                                    case 2:
1107                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1108                                                                                            start_y - iDiamondSize, 2 + 4);
1109                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1110                                                                                            start_y + iDiamondSize, 2 + 8);
1111                                            break;
1112                                    case 1:
1113                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1114                                                                                            start_y - iDiamondSize, 1 + 4);
1115                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1116                                                                                            start_y + iDiamondSize, 1 + 8);
1117                                            break;
1118                                    case 2 + 4:
1119                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1120                                                                                            start_y - iDiamondSize, 1 + 4);
1121                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1122                                                                                            start_y - iDiamondSize, 2 + 4);
1123                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1124                                                                                            start_y + iDiamondSize, 2 + 8);
1125                                            break;
1126                                    case 4:
1127                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1128                                                                                            start_y - iDiamondSize, 2 + 4);
1129                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1130                                                                                            start_y - iDiamondSize, 1 + 4);
1131                                            break;
1132                                    case 8:
1133                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1134                                                                                            start_y + iDiamondSize, 2 + 8);
1135                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1136                                                                                            start_y + iDiamondSize, 1 + 8);
1137                                            break;
1138                                    case 1 + 4:
1139                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1140                                                                                            start_y + iDiamondSize, 1 + 8);
1141                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1142                                                                                            start_y - iDiamondSize, 1 + 4);
1143                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1144                                                                                            start_y - iDiamondSize, 2 + 4);
1145                                            break;
1146                                    case 2 + 8:
1147                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1148                                                                                            start_y - iDiamondSize, 1 + 4);
1149                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1150                                                                                            start_y + iDiamondSize, 1 + 8);
1151                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1152                                                                                            start_y + iDiamondSize, 2 + 8);
1153                                            break;
1154                                    case 1 + 8:
1155                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1156                                                                                            start_y - iDiamondSize, 2 + 4);
1157                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1158                                                                                            start_y + iDiamondSize, 2 + 8);
1159                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1160                                                                                            start_y + iDiamondSize, 1 + 8);
1161                                            break;
1162                                    default:                //1+2+4+8 == we didn't find anything at all
1163                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1164                                                                                            start_y - iDiamondSize, 1 + 4);
1165                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1166                                                                                            start_y + iDiamondSize, 1 + 8);
1167                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1168                                                                                            start_y - iDiamondSize, 2 + 4);
1169                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1170                                                                                            start_y + iDiamondSize, 2 + 8);
1171                                            break;
1172                                    }
1173                                    if (!(iDirection))
1174                                            break;          //ok, the end. really
1175                                    else {
1176                                            bDirection = iDirection;
1177                                            start_x = currMV->x;
1178                                            start_y = currMV->y;
1179                                    }
1180                            }
1181                    }
1182                    while (1);                              //forever
1183            }
1184            return iMinSAD;
1185    }
1186    
1187    
1188    int32_t
1189    Full8_MainSearch(const uint8_t * const pRef,
1190                                     const uint8_t * const pRefH,
1191                                     const uint8_t * const pRefV,
1192                                     const uint8_t * const pRefHV,
1193                                     const uint8_t * const cur,
1194                                     const int x,
1195                                     const int y,
1196                               const int start_x,
1197                               const int start_y,
1198                               int iMinSAD,
1199                               VECTOR * const currMV,
1200                               const int center_x,
1201                               const int center_y,
1202                                     const int32_t min_dx,
1203                                     const int32_t max_dx,
1204                                     const int32_t min_dy,
1205                                     const int32_t max_dy,
1206                                     const int32_t iEdgedWidth,
1207                                     const int32_t iDiamondSize,
1208                                     const int32_t iFcode,
1209                                     const int32_t iQuant,
1210                                     int iFound)
1211    {
1212            int32_t iSAD;
1213            int32_t dx, dy;
1214            VECTOR backupMV;
1215    
1216            backupMV.x = start_x;
1217            backupMV.y = start_y;
1218    
1219            for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1220                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
1221                            NOCHECK_MV8_CANDIDATE(dx, dy);
1222    
1223            return iMinSAD;
1224    }
1225    
1226    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1227    
1228    int32_t
1229    Halfpel16_Refine(const uint8_t * const pRef,
1230                                     const uint8_t * const pRefH,
1231                                     const uint8_t * const pRefV,
1232                                     const uint8_t * const pRefHV,
1233                                     const uint8_t * const cur,
1234                                     const int x,
1235                                     const int y,
1236                                     VECTOR * const currMV,
1237                                     int32_t iMinSAD,
1238                               const int center_x,
1239                               const int center_y,
1240                                     const int32_t min_dx,
1241                                     const int32_t max_dx,
1242                                     const int32_t min_dy,
1243                                     const int32_t max_dy,
1244                                     const int32_t iFcode,
1245                                     const int32_t iQuant,
1246                                     const int32_t iEdgedWidth)
1247    {
1248    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1249    
1250            int32_t iSAD;
1251            VECTOR backupMV = *currMV;
1252    
1253            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1254            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y - 1);
1255            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1256            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y);
1257            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y);
1258            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1259            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y + 1);
1260            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1261    
1262            return iMinSAD;
1263    }
1264    
1265    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1266    
1267    
1268    
1269    int32_t
1270    PMVfastSearch16(const uint8_t * const pRef,
1271                                    const uint8_t * const pRefH,
1272                                    const uint8_t * const pRefV,
1273                                    const uint8_t * const pRefHV,
1274                                    const IMAGE * const pCur,
1275                                    const int x,
1276                                    const int y,
1277                                    const int start_x,
1278                                    const int start_y,
1279                                    const int center_x,
1280                                    const int center_y,
1281                                    const uint32_t MotionFlags,
1282                                    const uint32_t iQuant,
1283                                    const uint32_t iFcode,
1284                                    const MBParam * const pParam,
1285                                    const MACROBLOCK * const pMBs,
1286                                    const MACROBLOCK * const prevMBs,
1287                                    VECTOR * const currMV,
1288                                    VECTOR * const currPMV)
1289    {
1290            const uint32_t iWcount = pParam->mb_width;
1291            const int32_t iWidth = pParam->width;
1292            const int32_t iHeight = pParam->height;
1293            const int32_t iEdgedWidth = pParam->edged_width;
1294    
1295            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
1296    
1297          int32_t iDiamondSize;          int32_t iDiamondSize;
1298    
# Line 889  Line 1309 
1309          VECTOR pmv[4];          VECTOR pmv[4];
1310          int32_t psad[4];          int32_t psad[4];
1311    
1312          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1313    
1314          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1315    
1316          static int32_t threshA,threshB;          int32_t threshA, threshB;
1317          int32_t bPredEq;          int32_t bPredEq;
1318          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1319    
1320  /* Get maximum range */  /* Get maximum range */
1321          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,
1322                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1323    
1324  /* 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 */
1325    
1326          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1327          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1328          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1329          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1330          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1331          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1332    
1333          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1334            //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1335            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1336    
1337          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1338                  threshA =  512;                  threshA =  512;
1339                  threshB = 1024;                  threshB = 1024;
1340            } else {
         }  
         else  
         {  
1341                  threshA = psad[0];                  threshA = psad[0];
1342                  threshB = threshA+256;                  threshB = threshA+256;
1343                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1344                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1345                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1346                            threshA = 1024;
1347                    if (threshB > 1792)
1348                            threshB = 1792;
1349          }          }
1350    
1351          iFound=0;          iFound=0;
1352    
 /* 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],prevMB->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;  
   
1353  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1354     MinSAD=SAD     MinSAD=SAD
1355     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 956  Line 1357 
1357     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1358  */  */
1359    
1360            currMV->x = start_x;
1361            currMV->y = start_y;
1362    
1363  // 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! */  
1364                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1365                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1366          }          }
1367    
1368          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1369                  currMV->x=max_dx;                  currMV->x=max_dx;
1370          }          }
1371          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1372                  currMV->x=min_dx;                  currMV->x=min_dx;
1373          }          }
1374          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1375                  currMV->y=max_dy;                  currMV->y=max_dy;
1376          }          }
1377          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1378                  currMV->y=min_dy;                  currMV->y=min_dy;
1379          }          }
1380    
1381          iMinSAD = sad16( cur,          iMinSAD =
1382                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1383                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1384          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1385            iMinSAD +=
1386          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1387          {                                            (uint8_t) iFcode, iQuant);
1388    
1389            if ((iMinSAD < 256) ||
1390                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1391                     ((int32_t) iMinSAD < prevMB->sad16))) {
1392                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1393                    {
1394                            if (!MVzero(*currMV)) {
1395                                    iMinSAD += MV16_00_BIAS;
1396                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1397                                    iMinSAD -= MV16_00_BIAS;
1398                            }
1399                    }
1400    
1401                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1402                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 997  Line 1404 
1404                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
1405          }          }
1406    
1407    
1408    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1409       vector of the median.
1410       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1411    */
1412    
1413            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1414                    iFound = 2;
1415    
1416    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1417       Otherwise select large Diamond Search.
1418    */
1419    
1420            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1421                    iDiamondSize = 1;               // halfpel!
1422            else
1423                    iDiamondSize = 2;               // halfpel!
1424    
1425            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1426                    iDiamondSize *= 2;
1427    
1428  /*  /*
1429     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.
1430     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
# Line 1006  Line 1434 
1434    
1435  // (0,0) is always possible  // (0,0) is always possible
1436    
1437            if (!MVzero(pmv[0]))
1438          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1439    
1440  // previous frame MV is always possible  // previous frame MV is always possible
1441    
1442            if (!MVzero(prevMB->mvs[0]))
1443                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1444          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1445    
1446  // left neighbour, if allowed  // left neighbour, if allowed
1447          if (x != 0)  
1448          {          if (!MVzero(pmv[1]))
1449                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1450                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1451                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1452                                            pmv[1].x = EVEN(pmv[1].x);
1453                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1454                  }                  }
1455    
1456                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1457          }          }
   
1458  // top neighbour, if allowed  // top neighbour, if allowed
1459          if (y != 0)          if (!MVzero(pmv[2]))
1460          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1461                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1462                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1463                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1464                                                    pmv[2].x = EVEN(pmv[2].x);
1465                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1466                  }                  }
1467                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1468    
1469  // top right neighbour, if allowed  // top right neighbour, if allowed
1470                  if ((uint32_t)x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1471                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1472                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1473                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1474                                                                            if (!MVequal(pmv[3], pmv[2])) {
1475                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1476                                                                                            pmv[3].x = EVEN(pmv[3].x);
1477                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1478                          }                          }
1479                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1480                                                                                                                             pmv[3].y);
1481                  }                  }
1482          }          }
1483    
1484          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) && (iSAD <= iQuant * 96) )          if ((MVzero(*currMV)) &&
1485                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1486                  iMinSAD -= MV16_00_BIAS;                  iMinSAD -= MV16_00_BIAS;
1487    
1488    
# Line 1049  Line 1490 
1490     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.
1491  */  */
1492    
1493          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1494          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1495                     ((int32_t) iMinSAD < prevMB->sad16))) {
1496                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1497                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1498                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1068  Line 1510 
1510     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1511  */  */
1512    
1513            if (MotionFlags & PMV_USESQUARES16)
1514                    MainSearchPtr = Square16_MainSearch;
1515            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1516                    MainSearchPtr = AdvDiamond16_MainSearch;
1517            else
1518                    MainSearchPtr = Diamond16_MainSearch;
1519    
1520          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1521    
1522    
1523  /* 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 */
1524          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1525                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1526                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1527                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1528                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1529                                                      iQuant, iFound);
1530    
1531          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1532                  *currMV = newMV;                  *currMV = newMV;
1533                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1534          }          }
1535    
1536          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1537  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1538    
1539                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1540                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1541                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1542                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1543                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1544                                                                      iDiamondSize, iFcode, iQuant, iFound);
1545    
1546                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1547                          *currMV = newMV;                          *currMV = newMV;
1548                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1549                  }                  }
1550                  }                  }
1551    
1552                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1553                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1554                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1555                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1556                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1557                                                                      iEdgedWidth, iDiamondSize, iFcode,
1558                                                                      iQuant, iFound);
1559    
1560                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1561                          *currMV = newMV;                          *currMV = newMV;
1562                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1563                  }                  }
# Line 1119  Line 1570 
1570    
1571  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1572          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1573                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1574                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1575                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1576                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1577    
1578  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1579          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1580          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1581          return iMinSAD;          return iMinSAD;
1582  }  }
1583    
# Line 1135  Line 1586 
1586    
1587    
1588    
1589  int32_t Diamond8_MainSearch(  int32_t
1590          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1591          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1592          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1593          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1594          const uint8_t * const cur,          const uint8_t * const cur,
1595          const int x, const int y,                                          const int x,
1596          int32_t startx, int32_t starty,                                          const int y,
1597                                            int32_t start_x,
1598                                            int32_t start_y,
1599          int32_t iMinSAD,          int32_t iMinSAD,
1600          VECTOR * const currMV,          VECTOR * const currMV,
1601          const VECTOR * const pmv,                                     const int center_x,
1602          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
1603          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1604                                            const int32_t max_dx,
1605                                            const int32_t min_dy,
1606                                            const int32_t max_dy,
1607          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1608          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1609          const int32_t iFcode,          const int32_t iFcode,
# Line 1159  Line 1615 
1615          int32_t iDirection=0;          int32_t iDirection=0;
1616          int32_t iSAD;          int32_t iSAD;
1617          VECTOR backupMV;          VECTOR backupMV;
1618          backupMV.x = startx;  
1619          backupMV.y = starty;          backupMV.x = start_x;
1620            backupMV.y = start_y;
1621    
1622  /* 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 */
1623    
# Line 1170  Line 1627 
1627          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1628    
1629          if (iDirection)          if (iDirection)
1630                  while (!iFound)                  while (!iFound) {
                 {  
1631                          iFound = 1;                          iFound = 1;
1632                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1633    
1634                          if ( iDirection != 2)                          if ( iDirection != 2)
1635                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1636                                                                                      backupMV.y, 1);
1637                          if ( iDirection != 1)                          if ( iDirection != 1)
1638                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1639                                                                                      backupMV.y, 2);
1640                          if ( iDirection != 4)                          if ( iDirection != 4)
1641                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1642                                                                                      backupMV.y - iDiamondSize, 3);
1643                          if ( iDirection != 3)                          if ( iDirection != 3)
1644                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1645                  }                                                                                    backupMV.y + iDiamondSize, 4);
1646          else          } else {
1647          {                  currMV->x = start_x;
1648                  currMV->x = startx;                  currMV->y = start_y;
                 currMV->y = starty;  
1649          }          }
1650          return iMinSAD;          return iMinSAD;
1651  }  }
1652    
1653  int32_t Halfpel8_Refine(  int32_t
1654          const uint8_t * const pRef,  Halfpel8_Refine_c(const uint8_t * const pRef,
1655          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1656          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1657          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1658          const uint8_t * const cur,          const uint8_t * const cur,
1659          const int x, const int y,                                  const int x,
1660                                    const int y,
1661          VECTOR * const currMV,          VECTOR * const currMV,
1662          int32_t iMinSAD,          int32_t iMinSAD,
1663          const VECTOR * const pmv,                             const int center_x,
1664          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1665          const int32_t min_dy, const int32_t max_dy,                                  const int32_t min_dx,
1666                                    const int32_t max_dx,
1667                                    const int32_t min_dy,
1668                                    const int32_t max_dy,
1669          const int32_t iFcode,          const int32_t iFcode,
1670          const int32_t iQuant,          const int32_t iQuant,
1671          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1228  Line 1690 
1690    
1691  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1692    
1693  int32_t PMVfastSearch8(  int32_t
1694                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1695                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1696                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1697                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1698                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1699                                          const int x, const int y,                             const int x,
1700                                          const int start_x, const int start_y,                             const int y,
1701                               const int start_x,
1702                               const int start_y,
1703                                    const int center_x,
1704                                    const int center_y,
1705                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1706                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1707                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1263  Line 1729 
1729          int32_t psad[4];          int32_t psad[4];
1730          VECTOR newMV;          VECTOR newMV;
1731          VECTOR backupMV;          VECTOR backupMV;
1732            VECTOR startMV;
1733    
1734          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1735          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1736    
1737          static int32_t threshA,threshB;           int32_t threshA, threshB;
1738          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1739          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1740    
1741          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1742    
1743            MainSearch8FuncPtr MainSearchPtr;
1744    
1745            /* Init variables */
1746            startMV.x = start_x;
1747            startMV.y = start_y;
1748    
1749  /* Get maximum range */  /* Get maximum range */
1750          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
1751                    x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
1752    
1753          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
1754          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1755          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1756          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1757          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1758          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
1759    
1760            /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1761            //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
1762            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
1763    
1764            if ((x == 0) && (y == 0)) {
1765                    threshA = 512 / 4;
1766                    threshB = 1024 / 4;
1767    
1768            } else {
1769                    threshA = psad[0] / 4;  /* good estimate? */
1770                    threshB = threshA + 256 / 4;
1771                    if (threshA < 512 / 4)
1772                            threshA = 512 / 4;
1773                    if (threshA > 1024 / 4)
1774                            threshA = 1024 / 4;
1775                    if (threshB > 1792 / 4)
1776                            threshB = 1792 / 4;
1777            }
1778    
1779            iFound = 0;
1780    
1781    /* Step 4: Calculate SAD around the Median prediction.
1782       MinSAD=SAD
1783       If Motion Vector equal to Previous frame motion vector
1784       and MinSAD<PrevFrmSAD goto Step 10.
1785       If SAD<=256 goto Step 10.
1786    */
1787    
1788    
1789          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);  // Prepare for main loop
1790    
1791          if ((x==0) && (y==0) )  //  if (MotionFlags & PMV_USESQUARES8)
1792          {  //      MainSearchPtr = Square8_MainSearch;
1793                  threshA =  512/4;  //  else
                 threshB = 1024/4;  
1794    
1795          }          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1796                    MainSearchPtr = AdvDiamond8_MainSearch;
1797          else          else
1798          {                  MainSearchPtr = Diamond8_MainSearch;
                 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;  
         }  
1799    
         iFound=0;  
1800    
1801  /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion          *currMV = startMV;
1802    
1803            iMinSAD =
1804                    sad8(cur,
1805                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
1806                                                    iEdgedWidth), iEdgedWidth);
1807            iMinSAD +=
1808                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
1809                                             (uint8_t) iFcode, iQuant);
1810    
1811            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
1812                                                                    && ((int32_t) iMinSAD <
1813                                                                            prevMB->sad8[iSubBlock]))) {
1814                    if (MotionFlags & PMV_QUICKSTOP16)
1815                            goto PMVfast8_Terminate_without_Refine;
1816                    if (MotionFlags & PMV_EARLYSTOP16)
1817                            goto PMVfast8_Terminate_with_Refine;
1818            }
1819    
1820    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1821     vector of the median.     vector of the median.
1822     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1823  */  */
# Line 1312  Line 1825 
1825          if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) )          if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) )
1826                  iFound=2;                  iFound=2;
1827    
1828  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1829     Otherwise select large Diamond Search.     Otherwise select large Diamond Search.
1830  */  */
1831    
1832          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )          if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
1833                  iDiamondSize=1; // 1 halfpel!                  iDiamondSize=1; // 1 halfpel!
1834          else          else
1835                  iDiamondSize=2; // 2 halfpel = 1 full pixel!                  iDiamondSize=2; // 2 halfpel = 1 full pixel!
# Line 1324  Line 1837 
1837          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
1838                  iDiamondSize*=2;                  iDiamondSize*=2;
1839    
 /* Step 4: Calculate SAD around the Median prediction.  
    MinSAD=SAD  
    If Motion Vector equal to Previous frame motion vector  
    and MinSAD<PrevFrmSAD goto Step 10.  
    If SAD<=256 goto Step 10.  
 */  
   
   
 // Prepare for main loop  
   
         currMV->x=start_x;              /* start with mv16 */  
         currMV->y=start_y;  
   
         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;  
   
         if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock])) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )  
         {  
                 if (MotionFlags & PMV_QUICKSTOP16)  
                         goto PMVfast8_Terminate_without_Refine;  
                 if (MotionFlags & PMV_EARLYSTOP16)  
                         goto PMVfast8_Terminate_with_Refine;  
         }  
   
1840    
1841  /*  /*
1842     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.
# Line 1358  Line 1845 
1845     If MV is (0,0) subtract offset.     If MV is (0,0) subtract offset.
1846  */  */
1847    
1848  // 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);  
1849    
1850  // (0,0) is always possible          if (!MVequal(pmv[0], startMV))
1851                    CHECK_MV8_CANDIDATE(center_x, center_y);
1852    
1853    // (0,0) if needed
1854            if (!MVzero(pmv[0]))
1855                    if (!MVzero(startMV))
1856          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1857    
1858  // previous frame MV is always possible  // previous frame MV if needed
1859          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
1860                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
1861                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
1862                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
1863                                                                            prevMB->mvs[iSubBlock].y);
1864    
1865            if ((iMinSAD <= threshA) ||
1866                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1867                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1868                    if (MotionFlags & PMV_QUICKSTOP16)
1869                            goto PMVfast8_Terminate_without_Refine;
1870                    if (MotionFlags & PMV_EARLYSTOP16)
1871                            goto PMVfast8_Terminate_with_Refine;
1872            }
1873    
1874  // left neighbour, if allowed  // left neighbour, if allowed and needed
1875          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
1876          {                  if (!MVequal(pmv[1], startMV))
1877                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
1878                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
1879                                            if (!(MotionFlags & PMV_HALFPEL8)) {
1880                                                    pmv[1].x = EVEN(pmv[1].x);
1881                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1882                  }                  }
1883                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1884          }          }
1885    // top neighbour, if allowed and needed
1886  // top neighbour, if allowed          if (!MVzero(pmv[2]))
1887          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
1888          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
1889                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
1890                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
1891                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
1892                                                            pmv[2].x = EVEN(pmv[2].x);
1893                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1894                  }                  }
1895                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1896    
1897  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
1898                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
1899                  {                                                          if (!MVequal(pmv[3], startMV))
1900                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
1901                          {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
1902                                                                                    if (!MVequal(pmv[3], pmv[1]))
1903                                                                                            if (!MVequal(pmv[3], pmv[2])) {
1904                                                                                                    if (!
1905                                                                                                            (MotionFlags &
1906                                                                                                             PMV_HALFPEL8)) {
1907                                                                                                            pmv[3].x = EVEN(pmv[3].x);
1908                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1909                          }                          }
1910                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
1911                                                                                                                                            pmv[3].y);
1912                  }                  }
1913          }          }
1914    
1915          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) && (iSAD <= iQuant * 96) )          if ((MVzero(*currMV)) &&
1916                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1917                  iMinSAD -= MV8_00_BIAS;                  iMinSAD -= MV8_00_BIAS;
1918    
1919    
# Line 1405  Line 1921 
1921     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.
1922  */  */
1923    
1924          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
1925          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1926                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1927                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1928                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1929                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1426  Line 1943 
1943          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1944    
1945  /* 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 */
1946          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1947                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
1948                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
1949                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1950                                                      iQuant, iFound);
1951    
1952          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1953                  *currMV = newMV;                  *currMV = newMV;
1954                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1955          }          }
1956    
1957          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
1958  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1959    
1960                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1961                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1962                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1963                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
1964                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1965                                                                      iDiamondSize, iFcode, iQuant, iFound);
1966    
1967                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1968                          *currMV = newMV;                          *currMV = newMV;
1969                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1970                  }                  }
1971                  }                  }
1972    
1973                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1974                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1975                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1976                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
1977                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
1978                                                                      iQuant, iFound);
1979    
1980                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1981                          *currMV = newMV;                          *currMV = newMV;
1982                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1983                  }                  }
# Line 1474  Line 1990 
1990    
1991  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
1992          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1993                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1994                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1995                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1996                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
1997    
1998    
1999  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
2000          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2001          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2002    
2003          return iMinSAD;          return iMinSAD;
2004  }  }
2005    
2006  int32_t EPZSSearch16(  int32_t
2007                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2008                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2009                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2010                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2011                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2012                                          const int x, const int y,                           const int x,
2013                             const int y,
2014                            const int start_x,
2015                            const int start_y,
2016                            const int center_x,
2017                            const int center_y,
2018                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2019                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2020                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1524  Line 2045 
2045          int32_t psad[8];          int32_t psad[8];
2046    
2047          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2048          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
2049    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2050          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
2051          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
2052    
2053          static int32_t thresh2;           int32_t thresh2;
2054          int32_t bPredEq;          int32_t bPredEq;
2055          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2056    
2057          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2058    
2059          if (oldMBs == NULL)          if (oldMBs == NULL) {
2060          {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2061  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2062          }          }
2063          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2064    
2065  /* Get maximum range */  /* Get maximum range */
2066          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,
2067                          x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
2068    
2069          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
2070          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2071            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2072            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2073            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2074          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2075            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2076          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2077            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2078    
2079  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2080          MinSAD=SAD          MinSAD=SAD
# Line 1562  Line 2085 
2085    
2086  // Prepare for main loop  // Prepare for main loop
2087    
2088          *currMV=pmv[0];         /* current best := median prediction */          currMV->x = start_x;
2089          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2090          {  
2091            if (!(MotionFlags & PMV_HALFPEL16)) {
2092                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2093                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2094          }          }
# Line 1580  Line 2104 
2104    
2105  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2106    
2107          iMinSAD = sad16( cur,          iMinSAD =
2108                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2109                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2110          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2111            iMinSAD +=
2112                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2113                                              (uint8_t) iFcode, iQuant);
2114    
2115  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2116          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD < 256) ||
2117                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2118                     ((int32_t) iMinSAD < prevMB->sad16))) {
2119                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2120                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2121                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1597  Line 2125 
2125  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2126    
2127  // previous frame MV  // previous frame MV
2128          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
2129    
2130  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2131  // 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
2132    
2133          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2134                  thresh2 =  512;                  thresh2 =  512;
2135          }          } else {
         else  
         {  
2136  /* 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] */
2137    
2138                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1619  Line 2144 
2144    
2145    
2146  // left neighbour, if allowed  // left neighbour, if allowed
2147          if (x != 0)          if (x != 0) {
2148          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2149                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2150                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2151                  }                  }
2152                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2153          }          }
   
2154  // top neighbour, if allowed  // top neighbour, if allowed
2155          if (y != 0)          if (y != 0) {
2156          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2157                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2158                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2159                  }                  }
2160                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
2161    
2162  // top right neighbour, if allowed  // top right neighbour, if allowed
2163                  if ((uint32_t)x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
2164                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2165                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2166                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2167                          }                          }
2168                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1653  Line 2174 
2174  */  */
2175    
2176          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2177                  || ( MVequal(*currMV,pMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2178                  {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2179                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2180                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2181                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1663  Line 2184 
2184    
2185  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
2186    
2187          backupMV = pMB->mvs[0];                 // last MV          backupMV = prevMB->mvs[0];      // collocated MV
2188          backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X          backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2189          backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y          backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2190    
2191          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
2192    
2193  // left neighbour  // left neighbour
2194          if (x != 0)          if (x != 0)
2195                  CHECK_MV16_CANDIDATE((oldMB-1)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - 1)->mvs[0].x, (prevMB - 1)->mvs[0].y);
2196    
2197  // top neighbour  // top neighbour
2198          if (y != 0)          if (y != 0)
2199                  CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2200                                                             (prevMB - iWcount)->mvs[0].y);
2201    
2202    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2203    
2204            if ((uint32_t) x != iWcount - 1)
2205                    CHECK_MV16_CANDIDATE((prevMB + 1)->mvs[0].x, (prevMB + 1)->mvs[0].y);
2206    
2207    // bottom neighbour, dito
2208            if ((uint32_t) y != iHcount - 1)
2209                    CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2210                                                             (prevMB + iWcount)->mvs[0].y);
2211    
2212    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2213            if (iMinSAD <= thresh2) {
2214                    if (MotionFlags & PMV_QUICKSTOP16)
2215                            goto EPZS16_Terminate_without_Refine;
2216                    if (MotionFlags & PMV_EARLYSTOP16)
2217                            goto EPZS16_Terminate_with_Refine;
2218            }
2219    
2220    /************ (if Diamond Search)  **************/
2221    
2222            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2223    
2224            if (MotionFlags & PMV_USESQUARES16)
2225                    MainSearchPtr = Square16_MainSearch;
2226            else
2227             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2228                    MainSearchPtr = AdvDiamond16_MainSearch;
2229            else
2230                    MainSearchPtr = Diamond16_MainSearch;
2231    
2232    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2233    
2234            iSAD =
2235                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2236                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2237                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2238    
2239            if (iSAD < iMinSAD) {
2240                    *currMV = newMV;
2241                    iMinSAD = iSAD;
2242            }
2243    
2244    
2245            if (MotionFlags & PMV_EXTSEARCH16) {
2246    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2247    
2248                    if (!(MVequal(pmv[0], backupMV))) {
2249                            iSAD =
2250                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2251                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2252                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2253                                                                      2, iFcode, iQuant, 0);
2254                    }
2255    
2256                    if (iSAD < iMinSAD) {
2257                            *currMV = newMV;
2258                            iMinSAD = iSAD;
2259                    }
2260    
2261                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2262                            iSAD =
2263                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2264                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2265                                                                      max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2266    
2267                            if (iSAD < iMinSAD) {
2268                                    *currMV = newMV;
2269                                    iMinSAD = iSAD;
2270                            }
2271                    }
2272            }
2273    
2274    /***************        Choose best MV found     **************/
2275    
2276      EPZS16_Terminate_with_Refine:
2277            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2278                    iMinSAD =
2279                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2280                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2281                                                             iFcode, iQuant, iEdgedWidth);
2282    
2283      EPZS16_Terminate_without_Refine:
2284    
2285            *oldMB = *prevMB;
2286    
2287            currPMV->x = currMV->x - center_x;
2288            currPMV->y = currMV->y - center_y;
2289            return iMinSAD;
2290    }
2291    
2292    
2293    int32_t
2294    EPZSSearch8(const uint8_t * const pRef,
2295                            const uint8_t * const pRefH,
2296                            const uint8_t * const pRefV,
2297                            const uint8_t * const pRefHV,
2298                            const IMAGE * const pCur,
2299                            const int x,
2300                            const int y,
2301                            const int start_x,
2302                            const int start_y,
2303                            const int center_x,
2304                            const int center_y,
2305                            const uint32_t MotionFlags,
2306                            const uint32_t iQuant,
2307                            const uint32_t iFcode,
2308                            const MBParam * const pParam,
2309                            const MACROBLOCK * const pMBs,
2310                            const MACROBLOCK * const prevMBs,
2311                            VECTOR * const currMV,
2312                            VECTOR * const currPMV)
2313    {
2314    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
2315    
2316            const uint32_t iWcount = pParam->mb_width;
2317            const int32_t iWidth = pParam->width;
2318            const int32_t iHeight = pParam->height;
2319            const int32_t iEdgedWidth = pParam->edged_width;
2320    
2321            const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;
2322    
2323            int32_t iDiamondSize = 1;
2324    
2325            int32_t min_dx;
2326            int32_t max_dx;
2327            int32_t min_dy;
2328            int32_t max_dy;
2329    
2330            VECTOR newMV;
2331            VECTOR backupMV;
2332    
2333            VECTOR pmv[4];
2334            int32_t psad[8];
2335    
2336            const int32_t iSubBlock = ((y & 1) << 1) + (x & 1);
2337    
2338    //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2339            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2340    
2341            int32_t bPredEq;
2342            int32_t iMinSAD, iSAD = 9999;
2343    
2344            MainSearch8FuncPtr MainSearchPtr;
2345    
2346    /* Get maximum range */
2347            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2348                              iFcode);
2349    
2350    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2351    
2352            if (!(MotionFlags & PMV_HALFPEL8)) {
2353                    min_dx = EVEN(min_dx);
2354                    max_dx = EVEN(max_dx);
2355                    min_dy = EVEN(min_dy);
2356                    max_dy = EVEN(max_dy);
2357            }
2358            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2359            //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv[0].x, pmv[0].y, psad);
2360            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2361    
2362    
2363    /* Step 4: Calculate SAD around the Median prediction.
2364            MinSAD=SAD
2365            If Motion Vector equal to Previous frame motion vector
2366                    and MinSAD<PrevFrmSAD goto Step 10.
2367            If SAD<=256 goto Step 10.
2368    */
2369    
2370    // Prepare for main loop
2371    
2372    
2373            if (!(MotionFlags & PMV_HALFPEL8)) {
2374                    currMV->x = EVEN(currMV->x);
2375                    currMV->y = EVEN(currMV->y);
2376            }
2377    
2378            if (currMV->x > max_dx)
2379                    currMV->x = max_dx;
2380            if (currMV->x < min_dx)
2381                    currMV->x = min_dx;
2382            if (currMV->y > max_dy)
2383                    currMV->y = max_dy;
2384            if (currMV->y < min_dy)
2385                    currMV->y = min_dy;
2386    
2387    /***************** This is predictor SET A: only median prediction ******************/
2388    
2389    
2390            iMinSAD =
2391                    sad8(cur,
2392                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2393                                                    iEdgedWidth), iEdgedWidth);
2394            iMinSAD +=
2395                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2396                                             (uint8_t) iFcode, iQuant);
2397    
2398    
2399    // thresh1 is fixed to 256
2400            if (iMinSAD < 256 / 4) {
2401                    if (MotionFlags & PMV_QUICKSTOP8)
2402                            goto EPZS8_Terminate_without_Refine;
2403                    if (MotionFlags & PMV_EARLYSTOP8)
2404                            goto EPZS8_Terminate_with_Refine;
2405            }
2406    
2407    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2408    
2409    
2410    // MV=(0,0) is often a good choice
2411            CHECK_MV8_ZERO;
2412    
2413    // previous frame MV
2414            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2415    
2416    // left neighbour, if allowed
2417            if (psad[1] != MV_MAX_ERROR) {
2418                    if (!(MotionFlags & PMV_HALFPEL8)) {
2419                            pmv[1].x = EVEN(pmv[1].x);
2420                            pmv[1].y = EVEN(pmv[1].y);
2421                    }
2422                    CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2423            }
2424    // top neighbour, if allowed
2425            if (psad[2] != MV_MAX_ERROR) {
2426                    if (!(MotionFlags & PMV_HALFPEL8)) {
2427                            pmv[2].x = EVEN(pmv[2].x);
2428                            pmv[2].y = EVEN(pmv[2].y);
2429                    }
2430                    CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2431    
2432    // top right neighbour, if allowed
2433                    if (psad[3] != MV_MAX_ERROR) {
2434                            if (!(MotionFlags & PMV_HALFPEL8)) {
2435                                    pmv[3].x = EVEN(pmv[3].x);
2436                                    pmv[3].y = EVEN(pmv[3].y);
2437                            }
2438                            CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2439                    }
2440            }
2441    
2442    /*  // this bias is zero anyway, at the moment!
2443    
2444  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2445                    iMinSAD -= MV8_00_BIAS;
2446    
2447          if ((uint32_t)x != iWcount-1)  */
                 CHECK_MV16_CANDIDATE((pMB+1)->mvs[0].x,oldMB->mvs[0].y);  
2448    
2449  // bottom neighbour, dito  /* Terminate if MinSAD <= T_2
2450          if ((uint32_t)y != iHcount-1)     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2451                  CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);  */
2452    
2453  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
2454          if (iMinSAD <= thresh2)                  if (MotionFlags & PMV_QUICKSTOP8)
2455                  {                          goto EPZS8_Terminate_without_Refine;
2456                          if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_EARLYSTOP8)
2457                                  goto EPZS16_Terminate_without_Refine;                          goto EPZS8_Terminate_with_Refine;
                         if (MotionFlags & PMV_EARLYSTOP16)  
                                 goto EPZS16_Terminate_with_Refine;  
2458                  }                  }
2459    
2460  /************ (if Diamond Search)  **************/  /************ (Diamond Search)  **************/
2461    
2462          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2463    
2464  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */          if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2465                    iDiamondSize *= 2;
2466    
2467          if (MotionFlags & PMV_USESQUARES16)  /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2468                  EPZSMainSearchPtr = Square16_MainSearch;  
2469    // there is no EPZS^2 for inter4v at the moment
2470    
2471    //  if (MotionFlags & PMV_USESQUARES8)
2472    //      MainSearchPtr = Square8_MainSearch;
2473    //  else
2474    
2475            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2476                    MainSearchPtr = AdvDiamond8_MainSearch;
2477          else          else
2478                  EPZSMainSearchPtr = Diamond16_MainSearch;                  MainSearchPtr = Diamond8_MainSearch;
2479    
2480          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2481                          x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2482                          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,
2483                          2, iFcode, iQuant, 0);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2484                                                      iQuant, 0);
2485    
2486          if (iSAD < iMinSAD)  
2487          {          if (iSAD < iMinSAD) {
2488                  *currMV = newMV;                  *currMV = newMV;
2489                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2490          }          }
2491    
2492            if (MotionFlags & PMV_EXTSEARCH8) {
         if (MotionFlags & PMV_EXTSEARCH16)  
         {  
2493  /* 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) */
2494    
2495                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2496                  {                          iSAD =
2497                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2498                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2499                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2500                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
                 }  
2501    
2502                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2503                          *currMV = newMV;                          *currMV = newMV;
2504                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2505                  }                  }
2506                    }
2507    
2508                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2509                  {                          iSAD =
2510                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2511                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2512                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2513                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, /*iDiamondSize*/ 2, iFcode, iQuant, 0);                                                                    iQuant, 0);
2514    
2515                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2516                                  *currMV = newMV;                                  *currMV = newMV;
2517                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2518                          }                          }
# Line 1753  Line 2521 
2521    
2522  /***************        Choose best MV found     **************/  /***************        Choose best MV found     **************/
2523    
2524  EPZS16_Terminate_with_Refine:    EPZS8_Terminate_with_Refine:
2525          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2526                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2527                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2528                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2529                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
   
 EPZS16_Terminate_without_Refine:  
2530    
2531          *oldMB = *pMB;    EPZS8_Terminate_without_Refine:
2532    
2533          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2534          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2535          return iMinSAD;          return iMinSAD;
2536  }  }
2537    
2538    
2539  int32_t EPZSSearch8(  
2540                                          const uint8_t * const pRef,  int32_t
2541    PMVfastIntSearch16(const uint8_t * const pRef,
2542                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2543                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2544                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2545                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2546                                          const int x, const int y,                                  const int x,
2547                                          const int start_x, const int start_y,                                  const int y,
2548                            const int start_x,
2549                            const int start_y,
2550                            const int center_x,
2551                            const int center_y,
2552                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2553                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2554                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1792  Line 2563 
2563          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
2564          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
2565    
2566          const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;          const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2567            const VECTOR zeroMV = { 0, 0 };
2568    
2569          int32_t iDiamondSize=1;          int32_t iDiamondSize;
2570    
2571          int32_t min_dx;          int32_t min_dx;
2572          int32_t max_dx;          int32_t max_dx;
2573          int32_t min_dy;          int32_t min_dy;
2574          int32_t max_dy;          int32_t max_dy;
2575    
2576            int32_t iFound;
2577    
2578          VECTOR newMV;          VECTOR newMV;
2579          VECTOR backupMV;          VECTOR backupMV;                        /* just for PMVFAST */
2580    
2581          VECTOR pmv[4];          VECTOR pmv[4];
2582          int32_t psad[8];          int32_t psad[4];
2583    
2584          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          MainSearch16FuncPtr MainSearchPtr;
2585    
2586          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2587          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2588    
2589            int32_t threshA, threshB;
2590          int32_t bPredEq;          int32_t bPredEq;
2591          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD, iSAD;
2592    
         MainSearch8FuncPtr EPZSMainSearchPtr;  
2593    
2594  /* Get maximum range */  /* Get maximum range */
2595          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,
2596                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2597    
2598  /* 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 */
2599    
2600          if (!(MotionFlags & PMV_HALFPEL8 ))          if ((x == 0) && (y == 0)) {
2601          { min_dx = EVEN(min_dx);                  threshA = 512;
2602            max_dx = EVEN(max_dx);                  threshB = 1024;
2603            min_dy = EVEN(min_dy);  
2604            max_dy = EVEN(max_dy);                  bPredEq = 0;
2605          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */                  psad[0] = psad[1] = psad[2] = psad[3] = 0;
2606                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2607    
2608          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);          } else {
2609                    threshA = psad[0];
2610                    threshB = threshA + 256;
2611                    if (threshA < 512)
2612                            threshA = 512;
2613                    if (threshA > 1024)
2614                            threshA = 1024;
2615                    if (threshB > 1792)
2616                            threshB = 1792;
2617    
2618                    bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2619                    *currMV = pmv[0];                       /* current best := prediction */
2620            }
2621    
2622            iFound = 0;
2623    
2624  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2625          MinSAD=SAD          MinSAD=SAD
# Line 1840  Line 2628 
2628          If SAD<=256 goto Step 10.          If SAD<=256 goto Step 10.
2629  */  */
2630    
2631  // Prepare for main loop          if (currMV->x > max_dx) {
2632                    currMV->x = EVEN(max_dx);
2633            }
2634            if (currMV->x < min_dx) {
2635                    currMV->x = EVEN(min_dx);
2636            }
2637            if (currMV->y > max_dy) {
2638                    currMV->y = EVEN(max_dy);
2639            }
2640            if (currMV->y < min_dy) {
2641                    currMV->y = EVEN(min_dy);
2642            }
2643    
2644            iMinSAD =
2645                    sad16(cur,
2646                              get_iref_mv(pRef, x, y, 16, currMV,
2647                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2648            iMinSAD +=
2649                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2650                                              (uint8_t) iFcode, iQuant);
2651    
2652            if ((iMinSAD < 256) ||
2653                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2654                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2655                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
2656                    {
2657                            if (!MVzero(*currMV)) {
2658                                    iMinSAD += MV16_00_BIAS;
2659                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2660                                    iMinSAD -= MV16_00_BIAS;
2661                            }
2662                    }
2663    
2664          if (!(MotionFlags & PMV_HALFPEL8))                  if (MotionFlags & PMV_EARLYSTOP16)
2665          {                          goto PMVfastInt16_Terminate_with_Refine;
                 currMV->x = EVEN(currMV->x);  
                 currMV->y = EVEN(currMV->y);  
2666          }          }
2667    
         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;  
2668    
2669  /***************** This is predictor SET A: only median prediction ******************/  /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2670       vector of the median.
2671       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2672    */
2673    
2674            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2675                    iFound = 2;
2676    
2677          iMinSAD = sad8( cur,  /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2678                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),     Otherwise select large Diamond Search.
2679                  iEdgedWidth);  */
         iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;  
2680    
2681            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2682                    iDiamondSize = 2;               // halfpel units!
2683            else
2684                    iDiamondSize = 4;               // halfpel units!
2685    
2686  // thresh1 is fixed to 256  /*
2687          if (iMinSAD < 256/4 )     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2688                  {     Also calculate (0,0) but do not subtract offset.
2689                          if (MotionFlags & PMV_QUICKSTOP8)     Let MinSAD be the smallest SAD up to this point.
2690                                  goto EPZS8_Terminate_without_Refine;     If MV is (0,0) subtract offset.
2691                          if (MotionFlags & PMV_EARLYSTOP8)  */
                                 goto EPZS8_Terminate_with_Refine;  
                 }  
2692    
2693  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  // (0,0) is often a good choice
2694    
2695  // previous frame MV          if (!MVzero(pmv[0]))
2696          CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);                  CHECK_MV16_ZERO;
2697    
2698  // MV=(0,0) is often a good choice  // previous frame MV is always possible
2699    
2700          CHECK_MV8_ZERO;          if (!MVzero(prevMB->i_mvs[0]))
2701                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2702                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2703    
2704  /* Terminate if MinSAD <= T_2  // left neighbour, if allowed
2705     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]  
2706            if (!MVzero(pmv[1]))
2707                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2708                            if (!MVequal(pmv[1], pmv[0]))
2709                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2710    
2711    // top neighbour, if allowed
2712            if (!MVzero(pmv[2]))
2713                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
2714                            if (!MVequal(pmv[2], pmv[0]))
2715                                    if (!MVequal(pmv[2], pmv[1]))
2716                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2717    
2718    // top right neighbour, if allowed
2719                                            if (!MVzero(pmv[3]))
2720                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
2721                                                            if (!MVequal(pmv[3], pmv[0]))
2722                                                                    if (!MVequal(pmv[3], pmv[1]))
2723                                                                            if (!MVequal(pmv[3], pmv[2]))
2724                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
2725                                                                                                                             pmv[3].y);
2726    
2727            if ((MVzero(*currMV)) &&
2728                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2729                    iMinSAD -= MV16_00_BIAS;
2730    
2731    
2732    /* Step 6: If MinSAD <= thresa goto Step 10.
2733       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2734  */  */
2735    
2736          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if ((iMinSAD <= threshA) ||
2737                  {                  (MVequal(*currMV, prevMB->i_mvs[0]) &&
2738                          if (MotionFlags & PMV_QUICKSTOP8)                   ((int32_t) iMinSAD < prevMB->i_sad16))) {
                                 goto EPZS8_Terminate_without_Refine;  
                         if (MotionFlags & PMV_EARLYSTOP8)  
                                 goto EPZS8_Terminate_with_Refine;  
                 }  
2739    
2740  /************ (if Diamond Search)  **************/                  if (MotionFlags & PMV_EARLYSTOP16)
2741                            goto PMVfastInt16_Terminate_with_Refine;
2742            }
2743    
         backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */  
2744    
2745          if (!(MotionFlags & PMV_HALFPELDIAMOND8))  /************ (Diamond Search)  **************/
2746                  iDiamondSize *= 2;  /*
2747       Step 7: Perform Diamond search, with either the small or large diamond.
2748       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
2749       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
2750       If center then goto step 10.
2751       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
2752       Refine by using small diamond and goto step 10.
2753    */
2754    
2755  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */          if (MotionFlags & PMV_USESQUARES16)
2756                    MainSearchPtr = Square16_MainSearch;
2757            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2758                    MainSearchPtr = AdvDiamond16_MainSearch;
2759            else
2760                    MainSearchPtr = Diamond16_MainSearch;
2761    
2762  //      if (MotionFlags & PMV_USESQUARES8)          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
 //              EPZSMainSearchPtr = Square8_MainSearch;  
 //      else  
                 EPZSMainSearchPtr = Diamond8_MainSearch;  
2763    
         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);  
2764    
2765    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2766            iSAD =
2767                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2768                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2769                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2770                                                      iQuant, iFound);
2771    
2772          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2773                  *currMV = newMV;                  *currMV = newMV;
2774                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2775          }          }
2776    
2777          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH16) {
2778          {  /* 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) */  
2779    
2780                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2781                  {                          iSAD =
2782                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2783                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2784                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2785                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, iFound);
2786    
2787                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2788                                  *currMV = newMV;                                  *currMV = newMV;
2789                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2790                          }                          }
2791                  }                  }
2792    
2793                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2794                  {                          iSAD =
2795                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2796                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2797                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2798                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, iFound);
2799    
2800                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2801                                  *currMV = newMV;                                  *currMV = newMV;
2802                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2803                          }                          }
2804                  }                  }
2805          }          }
2806    
2807  /***************        Choose best MV found     **************/  /*
2808       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
2809    */
2810    
2811  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);  
2812    
2813  EPZS8_Terminate_without_Refine:          pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
2814            pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
2815    
2816          currPMV->x = currMV->x - pmv[0].x;          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2817          currPMV->y = currMV->y - pmv[0].y;                  iMinSAD =
2818                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2819                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2820                                                             iFcode, iQuant, iEdgedWidth);
2821    
2822            pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
2823    
2824    PMVfastInt16_Terminate_without_Refine:
2825            currPMV->x = currMV->x - center_x;
2826            currPMV->y = currMV->y - center_y;
2827          return iMinSAD;          return iMinSAD;
2828  }  }
2829    
2830    
2831    
   
   
2832  /* ***********************************************************  /* ***********************************************************
2833          bvop motion estimation          bvop motion estimation
2834  // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)  // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
2835  ***************************************************************/  ***************************************************************/
2836    
 /*  
 void MotionEstimationBVOP(  
                         MBParam * const pParam,  
                         FRAMEINFO * const frame,  
2837    
2838    #define DIRECT_PENALTY 0
2839    #define DIRECT_UPPERLIMIT 256   // never use direct mode if SAD is larger than this
2840    
2841    void
2842    MotionEstimationBVOP(MBParam * const pParam,
2843                                             FRAMEINFO * const frame,
2844                                             const int32_t time_bp,
2845                                             const int32_t time_pp,
2846                          // forward (past) reference                          // forward (past) reference
2847                          const MACROBLOCK * const f_mbs,                          const MACROBLOCK * const f_mbs,
2848                      const IMAGE * const f_ref,                      const IMAGE * const f_ref,
# Line 2000  Line 2856 
2856                      const IMAGE * const b_refV,                      const IMAGE * const b_refV,
2857                          const IMAGE * const b_refHV)                          const IMAGE * const b_refHV)
2858  {  {
2859      const uint32_t mb_width = pParam->mb_width;          const int mb_width = pParam->mb_width;
2860      const uint32_t mb_height = pParam->mb_height;          const int mb_height = pParam->mb_height;
2861          const int32_t edged_width = pParam->edged_width;          const int edged_width = pParam->edged_width;
2862    
2863          int32_t i,j;          int i, j, k;
2864    
2865          int32_t f_sad16;          static const VECTOR zeroMV={0,0};
2866          int32_t b_sad16;  
2867          int32_t i_sad16;          int f_sad16;    /* forward (as usual) search */
2868          int32_t d_sad16;          int b_sad16;    /* backward (only in b-frames) search */
2869          int32_t best_sad;          int i_sad16;    /* interpolated (both direction, b-frames only) */
2870            int d_sad16;    /* direct mode (assume linear motion) */
2871    
2872            int best_sad;
2873    
2874            VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
2875          VECTOR pmv_dontcare;          VECTOR pmv_dontcare;
2876    
2877            int f_count=0;
2878            int b_count=0;
2879            int i_count=0;
2880            int d_count=0;
2881            int s_count=0;
2882    
2883            const int64_t TRB = (int32_t)time_pp - (int32_t)time_bp;
2884        const int64_t TRD = (int32_t)time_pp;
2885    
2886            // fprintf(stderr,"TRB = %lld  TRD = %lld  time_bp =%d time_pp =%d\n\n",TRB,TRD,time_bp,time_pp);
2887          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
2888      for (j = 0; j < mb_height; j++)          for (j = 0; j < mb_height; j++) {
2889          {  
2890                  for (i = 0; i < mb_width; i++)                  f_predMV = zeroMV;      /* prediction is reset at left boundary */
2891                  {                  b_predMV = zeroMV;
2892    
2893                    for (i = 0; i < mb_width; i++) {
2894                          MACROBLOCK *mb = &frame->mbs[i + j*mb_width];                          MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
2895                          const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];                          const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
2896                          const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];                          const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
2897    
2898                          if (b_mb->mode == MODE_INTER                          mb->deltamv=zeroMV;
2899                                  && b_mb->cbp == 0  
2900                                  && b_mb->mvs[0].x == 0  /* special case, if collocated block is SKIPed: encoding is forward(0,0)  */
2901                                  && b_mb->mvs[0].y == 0)  
2902                          {  #ifndef _DISABLE_SKIP
2903                                  mb->mode = MB_IGNORE;                          if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
2904                                    b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {
2905                                    mb->mode = MODE_NOT_CODED;
2906                                  mb->mvs[0].x = 0;                                  mb->mvs[0].x = 0;
2907                                  mb->mvs[0].y = 0;                                  mb->mvs[0].y = 0;
2908                                  mb->b_mvs[0].x = 0;                                  mb->b_mvs[0].x = 0;
2909                                  mb->b_mvs[0].y = 0;                                  mb->b_mvs[0].y = 0;
2910                                  continue;                                  continue;
2911                          }                          }
2912    #endif
2913    
2914                            d_sad16 = DIRECT_PENALTY;
2915    
2916                            if (b_mb->mode == MODE_INTER4V)
2917                            {
2918    
2919                            /* same method of scaling as in decoder.c, so we copy from there */
2920                        for (k = 0; k < 4; k++) {
2921    
2922                                            mb->directmv[k] = b_mb->mvs[k];
2923    
2924                                            mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
2925                        mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
2926                                                                                    ? ((TRB - TRD) * mb->directmv[k].x) / TRD
2927                                                : mb->mvs[k].x - mb->directmv[k].x);
2928    
2929                        mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
2930                            mb->b_mvs[k].y = (int32_t) ((mb->directmv[k].y == 0)
2931                                                                                    ? ((TRB - TRD) * mb->directmv[k].y) / TRD
2932                                                : mb->mvs[k].y - mb->directmv[k].y);
2933    
2934                                            d_sad16 +=
2935                                                    sad8bi(frame->image.y + 2*(i+(k&1))*8 + 2*(j+(k>>1))*8*edged_width,
2936                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2937                                                                    2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->mvs[k], edged_width),
2938                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2939                                                                    2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->b_mvs[k], edged_width),
2940                                                      edged_width);
2941                                    }
2942                            }
2943                            else
2944                            {
2945                                    mb->directmv[3] = mb->directmv[2] = mb->directmv[1] =
2946                                    mb->directmv[0] = b_mb->mvs[0];
2947    
2948                                    mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
2949                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
2950                                                                            ? ((TRB - TRD) * mb->directmv[0].x) / TRD
2951                                        : mb->mvs[0].x - mb->directmv[0].x);
2952    
2953                        mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
2954                    mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
2955                                                                            ? ((TRB - TRD) * mb->directmv[0].y) / TRD
2956                                        : mb->mvs[0].y - mb->directmv[0].y);
2957    
2958                                    d_sad16 += sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
2959                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2960                                                                    i, j, 16, &mb->mvs[0], edged_width),
2961                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2962                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
2963                                                      edged_width);
2964    
2965                }
2966                        d_sad16 += calc_delta_16(mb->deltamv.x, mb->deltamv.y, 1, frame->quant);
2967    
2968                          // forward search                          // forward search
2969                          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,
2970                                                  &frame->image,                                                  &frame->image, i, j,
2971                                                  i, j,                                                  mb->mvs[0].x, mb->mvs[0].y,                     /* start point f_directMV */
2972                                                  frame->motion_flags,  frame->quant, frame->fcode,                                                  f_predMV.x, f_predMV.y,                         /* center is f-prediction */
2973                                                  pParam,                                                  frame->motion_flags,
2974                                                  f_mbs,                                                  frame->quant, frame->fcode, pParam,
2975                                                  &mb->mvs[0], &pmv_dontcare);    // ignore pmv                                                  f_mbs, f_mbs,
2976                                                    &mb->mvs[0], &pmv_dontcare);
2977    
2978    
2979                          // backward search                          // backward search
2980                          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,
2981                                                  &frame->image,                                                  &frame->image, i, j,
2982                                                  i, j,                                                  mb->b_mvs[0].x, mb->b_mvs[0].y,         /* start point b_directMV */
2983                                                  frame->motion_flags,  frame->quant, frame->bcode,                                                  b_predMV.x, b_predMV.y,                         /* center is b-prediction */
2984                                                  pParam,                                                  frame->motion_flags,
2985                                                  b_mbs,                                                  frame->quant, frame->bcode, pParam,
2986                                                  &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv                                                  b_mbs, b_mbs,
2987                                                    &mb->b_mvs[0], &pmv_dontcare);
2988                          // interpolate search (simple, but effective)  
2989                          i_sad16 = sad16bi_c(                          i_sad16 =
2990                                          frame->image.y + i*16 + j*16*edged_width,                                  sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
2991                                          get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                                    get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2992                                                  i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),                                                                  i, j, 16, &mb->mvs[0], edged_width),
2993                                          get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                                                    get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2994                                                  i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),                                                                  i, j, 16, &mb->b_mvs[0], edged_width),
2995                                          edged_width);                                          edged_width);
2996                        i_sad16 += calc_delta_16(mb->mvs[0].x-f_predMV.x, mb->mvs[0].y-f_predMV.y,
2997                                                                    frame->fcode, frame->quant);
2998                        i_sad16 += calc_delta_16(mb->b_mvs[0].x-b_predMV.x, mb->b_mvs[0].y-b_predMV.y,
2999                                                                    frame->bcode, frame->quant);
3000    
3001                          // TODO: direct search                          // TODO: direct search
3002                          // predictor + range of [-32,32]                          // predictor + delta vector in range [-32,32] (fcode=1)
                         d_sad16 = 65535;  
3003    
3004                            i_sad16 = 65535;
3005                            f_sad16 = 65535;
3006                            b_sad16 = 65535;
3007    //                      d_sad16 = 65535;
3008    
3009                          if (f_sad16 < b_sad16)                          if (f_sad16 < b_sad16) {
                         {  
3010                                  best_sad = f_sad16;                                  best_sad = f_sad16;
3011                                  mb->mode = MB_FORWARD;                                  mb->mode = MODE_FORWARD;
3012                          }                          } else {
                         else  
                         {  
3013                                  best_sad = b_sad16;                                  best_sad = b_sad16;
3014                                  mb->mode = MB_BACKWARD;                                  mb->mode = MODE_BACKWARD;
3015                          }                          }
3016    
3017                          if (i_sad16 < best_sad)                          if (i_sad16 < best_sad) {
                         {  
3018                                  best_sad = i_sad16;                                  best_sad = i_sad16;
3019                                  mb->mode = MB_INTERPOLATE;                                  mb->mode = MODE_INTERPOLATE;
3020                          }                          }
3021    
3022                          if (d_sad16 < best_sad)                          if (d_sad16 < best_sad) {
3023    
3024                                    if (b_mb->mode == MODE_INTER4V)
3025                                    {
3026    
3027                                    /* same method of scaling as in decoder.c, so we copy from there */
3028                                for (k = 0; k < 4; k++) {
3029    
3030                                                    mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3031                                mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3032                                                                                            ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3033                                                        : mb->mvs[k].x - mb->directmv[k].x);
3034    
3035                                mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3036                            mb->b_mvs[k].y = (int32_t) ((mb->directmv[k].y == 0)
3037                                                                                            ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3038                                                : mb->mvs[k].y - mb->directmv[k].y);
3039                                            }
3040                                    }
3041                                    else
3042                          {                          {
3043                                            mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3044    
3045                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3046                                                                                    ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3047                                            : mb->mvs[0].x - mb->directmv[0].x);
3048    
3049                                mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3050    
3051                            mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
3052                                                                                    ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3053                                                : mb->mvs[0].y - mb->directmv[0].y);
3054    
3055                                            mb->mvs[3] = mb->mvs[2] = mb->mvs[1] = mb->mvs[0];
3056                                            mb->b_mvs[3] = mb->b_mvs[2] = mb->b_mvs[1] = mb->b_mvs[0];
3057                    }
3058    
3059                                  best_sad = d_sad16;                                  best_sad = d_sad16;
3060                                  mb->mode = MB_DIRECT;                                  mb->mode = MODE_DIRECT;
3061                                    mb->mode = MODE_INTERPOLATE;            // direct mode still broken :-(
3062                          }                          }
3063    
3064                            switch (mb->mode)
3065                            {
3066                                    case MODE_FORWARD:
3067                                            f_count++;
3068                                            f_predMV = mb->mvs[0];
3069                                            break;
3070                                    case MODE_BACKWARD:
3071                                            b_count++;
3072                                            b_predMV = mb->b_mvs[0];
3073    
3074                                            break;
3075                                    case MODE_INTERPOLATE:
3076                                            i_count++;
3077                                            f_predMV = mb->mvs[0];
3078                                            b_predMV = mb->b_mvs[0];
3079                                            break;
3080                                    case MODE_DIRECT:
3081                                            d_count++;
3082                                            break;
3083                                    default:
3084                                            s_count++;              // ???
3085                                            break;
3086                  }                  }
3087    
3088          }          }
3089  }  }
3090    
3091  */  #ifdef _DEBUG_BFRAME_STAT
3092            fprintf(stderr,"B-Stat: F: %04d   B: %04d   I: %04d  D: %04d   S: %04d\n",
3093                                    f_count,b_count,i_count,d_count,s_count);
3094    #endif
3095    
3096    }

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

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