[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 136, Thu Apr 25 06:55:00 2002 UTC revision 1001, Sat May 3 10:05:55 2003 UTC
# Line 1  Line 1 
1  /**************************************************************************  /**************************************************************************
2   *   *
3   *  Modifications:   *      XVID MPEG-4 VIDEO CODEC
4     *      motion estimation
5   *   *
6   *      25.04.2002 partial prevMB conversion   *      This program is an implementation of a part of one or more MPEG-4
7   *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>   *      Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
8   *  14.04.2002 added MotionEstimationBVOP()   *      to use this software module in hardware or software products are
9   *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between   *      advised that its use may infringe existing patents or copyrights, and
10   *             EPZS and EPZS^2   *      any such use would be at such party's own risk.  The original
11   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop   *      developer of this software module and his/her company, and subsequent
12   *             PMVFast_Refine to support multiple searches with different start points   *      editors and their companies, will have no liability for use of this
13   *  07.01.2002 uv-block-based interpolation   *      software or modifications or derivatives thereof.
  *  06.01.2002 INTER/INTRA-decision is now done before any SEARCH8 (speedup)  
  *             changed INTER_BIAS to 150 (as suggested by suxen_drol)  
  *             removed halfpel refinement step in PMVfastSearch8 + quality=5  
  *             added new quality mode = 6 which performs halfpel refinement  
  *             filesize difference between quality 5 and 6 is smaller than 1%  
  *             (Isibaar)  
  *  31.12.2001 PMVfastSearch16 and PMVfastSearch8 (gruel)  
  *  30.12.2001 get_range/MotionSearchX simplified; blue/green bug fix  
  *  22.12.2001 commented best_point==99 check  
  *  19.12.2001 modified get_range (purple bug fix)  
  *  15.12.2001 moved pmv displacement from mbprediction  
  *  02.12.2001 motion estimation/compensation split (Isibaar)  
  *  16.11.2001 rewrote/tweaked search algorithms; pross@cs.rmit.edu.au  
  *  10.11.2001 support for sad16/sad8 functions  
  *  28.08.2001 reactivated MODE_INTER4V for EXT_MODE  
  *  24.08.2001 removed MODE_INTER4V_Q, disabled MODE_INTER4V for EXT_MODE  
  *  22.08.2001 added MODE_INTER4V_Q  
  *  20.08.2001 added pragma to get rid of internal compiler error with VC6  
  *             idea by Cyril. Thanks.  
14   *   *
15   *  Michael Militzer <isibaar@videocoding.de>   *      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  #include <assert.h>  #include <assert.h>
32  #include <stdio.h>  #include <stdio.h>
33  #include <stdlib.h>  #include <stdlib.h>
34    #include <string.h>     // memcpy
35    #include <math.h>       // lrint
36    
37  #include "../encoder.h"  #include "../encoder.h"
38  #include "../utils/mbfunctions.h"  #include "../utils/mbfunctions.h"
39  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
40  #include "../global.h"  #include "../global.h"
41  #include "../utils/timer.h"  #include "../utils/timer.h"
42    #include "../image/interpolate8x8.h"
43    #include "motion_est.h"
44  #include "motion.h"  #include "motion.h"
45  #include "sad.h"  #include "sad.h"
46    #include "../utils/emms.h"
47    #include "../dct/fdct.h"
48    
49  // very large value  /*****************************************************************************
50  #define MV_MAX_ERROR    (4096 * 256)   * Modified rounding tables -- declared in motion.h
51     * Original tables see ISO spec tables 7-6 -> 7-9
52  // stop search if sdelta < THRESHOLD   ****************************************************************************/
53  #define MV16_THRESHOLD  192  
54  #define MV8_THRESHOLD   56  const uint32_t roundtab[16] =
55    {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2 };
56  /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  
57  /* nb  = vop pixels * 2^(bpp-8) */  /* K = 4 */
58  #define MV16_00_BIAS    (128+1)  const uint32_t roundtab_76[16] =
59    { 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1 };
60    
61    /* K = 2 */
62    const uint32_t roundtab_78[8] =
63    { 0, 0, 1, 1, 0, 0, 0, 1  };
64    
65    /* K = 1 */
66    const uint32_t roundtab_79[4] =
67    { 0, 1, 0, 0 };
68    
69    #define INITIAL_SKIP_THRESH     (10)
70    #define FINAL_SKIP_THRESH       (50)
71    #define MAX_SAD00_FOR_SKIP      (20)
72    #define MAX_CHROMA_SAD_FOR_SKIP (22)
73    
74    #define CHECK_CANDIDATE(X,Y,D) { \
75    CheckCandidate((X),(Y), (D), &iDirection, data ); }
76    
77    /*****************************************************************************
78     * Code
79     ****************************************************************************/
80    
81    static __inline uint32_t
82    d_mv_bits(int x, int y, const VECTOR pred, const uint32_t iFcode, const int qpel, const int rrv)
83    {
84            int bits;
85            const int q = (1 << (iFcode - 1)) - 1;
86    
87            x <<= qpel;
88            y <<= qpel;
89            if (rrv) { x = RRV_MV_SCALEDOWN(x); y = RRV_MV_SCALEDOWN(y); }
90    
91            x -= pred.x;
92            bits = (x != 0 ? iFcode:0);
93            x = abs(x);
94            x += q;
95            x >>= (iFcode - 1);
96            bits += mvtab[x];
97    
98            y -= pred.y;
99            bits += (y != 0 ? iFcode:0);
100            y = abs(y);
101            y += q;
102            y >>= (iFcode - 1);
103            bits += mvtab[y];
104    
105            return bits;
106    }
107    
108    static int32_t ChromaSAD2(const int fx, const int fy, const int bx, const int by,
109                                                            const SearchData * const data)
110    {
111            int sad;
112            const uint32_t stride = data->iEdgedWidth/2;
113            uint8_t * f_refu = data->RefQ,
114                    * f_refv = data->RefQ + 8,
115                    * b_refu = data->RefQ + 16,
116                    * b_refv = data->RefQ + 24;
117            int offset = (fx>>1) + (fy>>1)*stride;
118    
119            switch (((fx & 1) << 1) | (fy & 1))     {
120                    case 0:
121                            f_refu = (uint8_t*)data->RefP[4] + offset;
122                            f_refv = (uint8_t*)data->RefP[5] + offset;
123                            break;
124                    case 1:
125                            interpolate8x8_halfpel_v(f_refu, data->RefP[4] + offset, stride, data->rounding);
126                            interpolate8x8_halfpel_v(f_refv, data->RefP[5] + offset, stride, data->rounding);
127                            break;
128                    case 2:
129                            interpolate8x8_halfpel_h(f_refu, data->RefP[4] + offset, stride, data->rounding);
130                            interpolate8x8_halfpel_h(f_refv, data->RefP[5] + offset, stride, data->rounding);
131                            break;
132                    default:
133                            interpolate8x8_halfpel_hv(f_refu, data->RefP[4] + offset, stride, data->rounding);
134                            interpolate8x8_halfpel_hv(f_refv, data->RefP[5] + offset, stride, data->rounding);
135                            break;
136            }
137    
138  /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */          offset = (bx>>1) + (by>>1)*stride;
139  #define INTER_BIAS      512          switch (((bx & 1) << 1) | (by & 1))     {
140                    case 0:
141                            b_refu = (uint8_t*)data->b_RefP[4] + offset;
142                            b_refv = (uint8_t*)data->b_RefP[5] + offset;
143                            break;
144                    case 1:
145                            interpolate8x8_halfpel_v(b_refu, data->b_RefP[4] + offset, stride, data->rounding);
146                            interpolate8x8_halfpel_v(b_refv, data->b_RefP[5] + offset, stride, data->rounding);
147                            break;
148                    case 2:
149                            interpolate8x8_halfpel_h(b_refu, data->b_RefP[4] + offset, stride, data->rounding);
150                            interpolate8x8_halfpel_h(b_refv, data->b_RefP[5] + offset, stride, data->rounding);
151                            break;
152                    default:
153                            interpolate8x8_halfpel_hv(b_refu, data->b_RefP[4] + offset, stride, data->rounding);
154                            interpolate8x8_halfpel_hv(b_refv, data->b_RefP[5] + offset, stride, data->rounding);
155                            break;
156            }
157    
158  /* Parameters which control inter/inter4v decision */          sad = sad8bi(data->CurU, b_refu, f_refu, stride);
159  #define IMV16X16                        5          sad += sad8bi(data->CurV, b_refv, f_refv, stride);
160    
161  /* vector map (vlc delta size) smoother parameters */          return sad;
162  #define NEIGH_TEND_16X16        2  }
 #define NEIGH_TEND_8X8          2  
163    
164    static int32_t
165    ChromaSAD(const int dx, const int dy, const SearchData * const data)
166    {
167            int sad;
168            const uint32_t stride = data->iEdgedWidth/2;
169            int offset = (dx>>1) + (dy>>1)*stride;
170    
171  // fast ((A)/2)*2          if (dx == data->temp[5] && dy == data->temp[6]) return data->temp[7]; //it has been checked recently
172  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)          data->temp[5] = dx; data->temp[6] = dy; // backup
173    
174            switch (((dx & 1) << 1) | (dy & 1))     {
175                    case 0:
176                            sad = sad8(data->CurU, data->RefP[4] + offset, stride);
177                            sad += sad8(data->CurV, data->RefP[5] + offset, stride);
178                            break;
179                    case 1:
180                            sad = sad8bi(data->CurU, data->RefP[4] + offset, data->RefP[4] + offset + stride, stride);
181                            sad += sad8bi(data->CurV, data->RefP[5] + offset, data->RefP[5] + offset + stride, stride);
182                            break;
183                    case 2:
184                            sad = sad8bi(data->CurU, data->RefP[4] + offset, data->RefP[4] + offset + 1, stride);
185                            sad += sad8bi(data->CurV, data->RefP[5] + offset, data->RefP[5] + offset + 1, stride);
186                            break;
187                    default:
188                            interpolate8x8_halfpel_hv(data->RefQ, data->RefP[4] + offset, stride, data->rounding);
189                            sad = sad8(data->CurU, data->RefQ, stride);
190    
191  int32_t PMVfastSearch16(                          interpolate8x8_halfpel_hv(data->RefQ, data->RefP[5] + offset, stride, data->rounding);
192                                          const uint8_t * const pRef,                          sad += sad8(data->CurV, data->RefQ, stride);
193                                          const uint8_t * const pRefH,                          break;
194                                          const uint8_t * const pRefV,          }
195                                          const uint8_t * const pRefHV,          data->temp[7] = sad; //backup, part 2
196                                          const IMAGE * const pCur,          return sad;
197                                          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);  
198    
199  int32_t EPZSSearch16(  static __inline const uint8_t *
200                                          const uint8_t * const pRef,  GetReferenceB(const int x, const int y, const uint32_t dir, const SearchData * const data)
201                                          const uint8_t * const pRefH,  {
202                                          const uint8_t * const pRefV,  //      dir : 0 = forward, 1 = backward
203                                          const uint8_t * const pRefHV,          const uint8_t *const *const direction = ( dir == 0 ? data->RefP : data->b_RefP );
204                                          const IMAGE * const pCur,          const int picture = ((x&1)<<1) | (y&1);
205                                          const int x, const int y,          const int offset = (x>>1) + (y>>1)*data->iEdgedWidth;
206                                          const uint32_t MotionFlags,          return direction[picture] + offset;
207                                          const uint32_t iQuant,  }
208                                          const uint32_t iFcode,  
209                                          const MBParam * const pParam,  // this is a simpler copy of GetReferenceB, but as it's __inline anyway, we can keep the two separate
210                                          const MACROBLOCK * const pMBs,  static __inline const uint8_t *
211                                          const MACROBLOCK * const prevMBs,  GetReference(const int x, const int y, const SearchData * const data)
212                                          VECTOR * const currMV,  {
213                                          VECTOR * const currPMV);          const int picture = ((x&1)<<1) | (y&1);
214            const int offset = (x>>1) + (y>>1)*data->iEdgedWidth;
215            return data->RefP[picture] + offset;
216    }
217    
218    static uint8_t *
219    Interpolate8x8qpel(const int x, const int y, const uint32_t block, const uint32_t dir, const SearchData * const data)
220    {
221    // create or find a qpel-precision reference picture; return pointer to it
222            uint8_t * Reference = data->RefQ + 16*dir;
223            const uint32_t iEdgedWidth = data->iEdgedWidth;
224            const uint32_t rounding = data->rounding;
225            const int halfpel_x = x/2;
226            const int halfpel_y = y/2;
227            const uint8_t *ref1, *ref2, *ref3, *ref4;
228    
229            ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
230            ref1 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
231            switch( ((x&1)<<1) + (y&1) ) {
232            case 3: // x and y in qpel resolution - the "corners" (top left/right and
233                            // bottom left/right) during qpel refinement
234                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
235                    ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
236                    ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
237                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
238                    ref3 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
239                    ref4 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
240                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
241                    break;
242    
243            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
244                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
245                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
246                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
247                    break;
248    
249  int32_t PMVfastSearch8(          case 2: // x qpel, y halfpel - left or right during qpel refinement
250                                          const uint8_t * const pRef,                  ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
251                                          const uint8_t * const pRefH,                  ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
252                                          const uint8_t * const pRefV,                  interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
253                                          const uint8_t * const pRefHV,                  break;
                                         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);  
254    
255  int32_t EPZSSearch8(          default: // pure halfpel position
256                                          const uint8_t * const pRef,                  return (uint8_t *) ref1;
                                         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);  
257    
258            }
259            return Reference;
260    }
261    
262  typedef int32_t (MainSearch16Func)(  static uint8_t *
263          const uint8_t * const pRef,  Interpolate16x16qpel(const int x, const int y, const uint32_t dir, const SearchData * const data)
264          const uint8_t * const pRefH,  {
265          const uint8_t * const pRefV,  // create or find a qpel-precision reference picture; return pointer to it
266          const uint8_t * const pRefHV,          uint8_t * Reference = data->RefQ + 16*dir;
267          const uint8_t * const cur,          const uint32_t iEdgedWidth = data->iEdgedWidth;
268          const int x, const int y,          const uint32_t rounding = data->rounding;
269          int32_t startx, int32_t starty,          const int halfpel_x = x/2;
270          int32_t iMinSAD,          const int halfpel_y = y/2;
271          VECTOR * const currMV,          const uint8_t *ref1, *ref2, *ref3, *ref4;
272          const VECTOR * const pmv,  
273          const int32_t min_dx, const int32_t max_dx,          ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
274          const int32_t min_dy, const int32_t max_dy,          switch( ((x&1)<<1) + (y&1) ) {
275          const int32_t iEdgedWidth,          case 3: // x and y in qpel resolution - the "corners" (top left/right and
276          const int32_t iDiamondSize,                          // bottom left/right) during qpel refinement
277          const int32_t iFcode,                  ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
278          const int32_t iQuant,                  ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
279          int iFound);                  ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
280                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
281                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
282                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
283                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
284                    break;
285    
286  typedef MainSearch16Func* MainSearch16FuncPtr;          case 1: // x halfpel, y qpel - top or bottom during qpel refinement
287                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
288                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
289                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
290                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
291                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
292                    break;
293    
294            case 2: // x qpel, y halfpel - left or right during qpel refinement
295                    ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
296                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
297                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
298                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
299                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
300                    break;
301    
302  typedef int32_t (MainSearch8Func)(          default: // pure halfpel position
303          const uint8_t * const pRef,                  return (uint8_t *) ref1;
304          const uint8_t * const pRefH,          }
305          const uint8_t * const pRefV,          return Reference;
306          const uint8_t * const pRefHV,  }
         const uint8_t * const cur,  
         const int x, const int y,  
         int32_t startx, int32_t starty,  
         int32_t iMinSAD,  
         VECTOR * const currMV,  
         const VECTOR * const pmv,  
         const int32_t min_dx, const int32_t max_dx,  
         const int32_t min_dy, const int32_t max_dy,  
         const int32_t iEdgedWidth,  
         const int32_t iDiamondSize,  
         const int32_t iFcode,  
         const int32_t iQuant,  
         int iFound);  
   
 typedef MainSearch8Func* MainSearch8FuncPtr;  
   
 // mv.length table  
 static const uint32_t mvtab[33] = {  
     1,  2,  3,  4,  6,  7,  7,  7,  
     9,  9,  9,  10, 10, 10, 10, 10,  
     10, 10, 10, 10, 10, 10, 10, 10,  
     10, 11, 11, 11, 11, 11, 11, 12, 12  
 };  
307    
308    /* CHECK_CANDIATE FUNCTIONS START */
309    
310  static __inline uint32_t mv_bits(int32_t component, const uint32_t iFcode)  static void
311    CheckCandidate16(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
312  {  {
313      if (component == 0)          int xc, yc;
314                  return 1;          const uint8_t * Reference;
315            VECTOR * current;
316            int32_t sad; uint32_t t;
317    
318      if (component < 0)          if ( (x > data->max_dx) || (x < data->min_dx)
319                  component = -component;                  || (y > data->max_dy) || (y < data->min_dy) ) return;
320    
321      if (iFcode == 1)          if (!data->qpel_precision) {
322      {                  Reference = GetReference(x, y, data);
323                  if (component > 32)                  current = data->currentMV;
324                      component = 32;                  xc = x; yc = y;
325            } else { // x and y are in 1/4 precision
326                  return mvtab[component] + 1;                  Reference = Interpolate16x16qpel(x, y, 0, data);
327                    xc = x/2; yc = y/2; //for chroma sad
328                    current = data->currentQMV;
329      }      }
330    
331      component += (1 << (iFcode - 1)) - 1;          sad = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
332      component >>= (iFcode - 1);          t = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
   
     if (component > 32)  
                 component = 32;  
333    
334      return mvtab[component] + 1 + iFcode - 1;          sad += (data->lambda16 * t * sad)>>10;
335  }          data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))>>10;
336    
337            if (data->chroma) sad += ChromaSAD(     (xc >> 1) + roundtab_79[xc & 0x3],
338                                                                                    (yc >> 1) + roundtab_79[yc & 0x3], data);
339    
340  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode)          if (sad < data->iMinSAD[0]) {
341  {                  data->iMinSAD[0] = sad;
342          return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));                  current[0].x = x; current[0].y = y;
343                    *dir = Direction;
344  }  }
345    
346  static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)          if (data->temp[1] < data->iMinSAD[1]) {
347                    data->iMinSAD[1] = data->temp[1]; current[1].x = x; current[1].y = y; }
348  {          if (data->temp[2] < data->iMinSAD[2]) {
349      return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));                  data->iMinSAD[2] = data->temp[2]; current[2].x = x; current[2].y = y; }
350            if (data->temp[3] < data->iMinSAD[3]) {
351                    data->iMinSAD[3] = data->temp[3]; current[3].x = x; current[3].y = y; }
352            if (data->temp[4] < data->iMinSAD[4]) {
353                    data->iMinSAD[4] = data->temp[4]; current[4].x = x; current[4].y = y; }
354  }  }
355    
356    static void
357    CheckCandidate8(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
358    {
359            int32_t sad; uint32_t t;
360            const uint8_t * Reference;
361            VECTOR * current;
362    
363            if ( (x > data->max_dx) || (x < data->min_dx)
364                    || (y > data->max_dy) || (y < data->min_dy) ) return;
365    
366            if (!data->qpel_precision) {
367                    Reference = GetReference(x, y, data);
368                    current = data->currentMV;
369            } else { // x and y are in 1/4 precision
370                    Reference = Interpolate8x8qpel(x, y, 0, 0, data);
371                    current = data->currentQMV;
372            }
373    
374            sad = sad8(data->Cur, Reference, data->iEdgedWidth);
375            t = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
376    
377  #ifndef SEARCH16          sad += (data->lambda8 * t * (sad+NEIGH_8X8_BIAS))>>10;
 #define SEARCH16        PMVfastSearch16  
 //#define SEARCH16      FullSearch16  
 //#define SEARCH16      EPZSSearch16  
 #endif  
   
 #ifndef SEARCH8  
 #define SEARCH8         PMVfastSearch8  
 //#define SEARCH8       EPZSSearch8  
 #endif  
378    
379  bool MotionEstimation(          if (sad < *(data->iMinSAD)) {
380          MBParam * const pParam,                  *(data->iMinSAD) = sad;
381          FRAMEINFO * const current,                  current->x = x; current->y = y;
382          FRAMEINFO * const reference,                  *dir = Direction;
383          const IMAGE * const pRefH,          }
384          const IMAGE * const pRefV,  }
         const IMAGE * const pRefHV,  
         const uint32_t iLimit)  
385    
386    static void
387    CheckCandidate32(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
388  {  {
389          const uint32_t iWcount = pParam->mb_width;          uint32_t t;
390          const uint32_t iHcount = pParam->mb_height;          const uint8_t * Reference;
         MACROBLOCK * pMBs = current->mbs;  
         IMAGE * pCurrent = &current->image;  
   
         MACROBLOCK * prevMBs = reference->mbs;  // previous frame  
         IMAGE * pRef = &reference->image;  
   
391    
392          uint32_t i, j, iIntra = 0;          if ( (!(x&1) && x !=0) || (!(y&1) && y !=0) || //non-zero even value
393                    (x > data->max_dx) || (x < data->min_dx)
394                    || (y > data->max_dy) || (y < data->min_dy) ) return;
395    
396          VECTOR mv16;          Reference = GetReference(x, y, data);
397          VECTOR pmv16;          t = d_mv_bits(x, y, data->predMV, data->iFcode, 0, 1);
398    
399          int32_t sad8 = 0;          data->temp[0] = sad32v_c(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
         int32_t sad16;  
         int32_t deviation;  
   
         if (sadInit)  
                 (*sadInit)();  
400    
401            data->temp[0] += (data->lambda16 * t * data->temp[0]) >> 10;
402            data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))>>10;
403    
404          /* eventhough we have a seperate prevMBs,          if (data->temp[0] < data->iMinSAD[0]) {
405             pmvfast/epsz does something "funny" with the previous frames data */                  data->iMinSAD[0] = data->temp[0];
406                    data->currentMV[0].x = x; data->currentMV[0].y = y;
407                    *dir = Direction; }
408    
409          for (i = 0; i < iHcount; i++)          if (data->temp[1] < data->iMinSAD[1]) {
410                  for (j = 0; j < iWcount; j++)                  data->iMinSAD[1] = data->temp[1]; data->currentMV[1].x = x; data->currentMV[1].y = y; }
411                  {          if (data->temp[2] < data->iMinSAD[2]) {
412                          pMBs[j + i * iWcount].mvs[0] = prevMBs[j + i * iWcount].mvs[0];                  data->iMinSAD[2] = data->temp[2]; data->currentMV[2].x = x; data->currentMV[2].y = y; }
413                          pMBs[j + i * iWcount].mvs[1] = prevMBs[j + i * iWcount].mvs[1];          if (data->temp[3] < data->iMinSAD[3]) {
414                          pMBs[j + i * iWcount].mvs[2] = prevMBs[j + i * iWcount].mvs[2];                  data->iMinSAD[3] = data->temp[3]; data->currentMV[3].x = x; data->currentMV[3].y = y; }
415                          pMBs[j + i * iWcount].mvs[3] = prevMBs[j + i * iWcount].mvs[3];          if (data->temp[4] < data->iMinSAD[4]) {
416                  }                  data->iMinSAD[4] = data->temp[4]; data->currentMV[4].x = x; data->currentMV[4].y = y; }
   
         /*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);  
417                  }                  }
         */  
418    
419          // note: i==horizontal, j==vertical  static void
420          for (i = 0; i < iHcount; i++)  CheckCandidate16no4v(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
                 for (j = 0; j < iWcount; j++)  
421                  {                  {
422                          MACROBLOCK *pMB = &pMBs[j + i * iWcount];          int32_t sad, xc, yc;
423                          MACROBLOCK *prevMB = &prevMBs[j + i * iWcount];          const uint8_t * Reference;
424            uint32_t t;
425                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,          VECTOR * current;
                                          j, i, current->motion_flags, current->quant, current->fcode,  
                                          pParam, pMBs, prevMBs, &mv16, &pmv16);  
                         pMB->sad16=sad16;  
   
426    
427                          /* decide: MODE_INTER or MODE_INTRA          if ( (x > data->max_dx) || ( x < data->min_dx)
428                             if (dev_intra < sad_inter - 2 * nb) use_intra                  || (y > data->max_dy) || (y < data->min_dy) ) return;
                         */  
429    
430                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);          if (data->rrv && (!(x&1) && x !=0) | (!(y&1) && y !=0) ) return; //non-zero even value
431    
432                          if (deviation < (sad16 - INTER_BIAS))          if (data->qpel_precision) { // x and y are in 1/4 precision
433                          {                  Reference = Interpolate16x16qpel(x, y, 0, data);
434                                  pMB->mode = MODE_INTRA;                  current = data->currentQMV;
435                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;                  xc = x/2; yc = y/2;
436                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;          } else {
437                    Reference = GetReference(x, y, data);
438                    current = data->currentMV;
439                    xc = x; yc = y;
440            }
441            t = d_mv_bits(x, y, data->predMV, data->iFcode,
442                                            data->qpel^data->qpel_precision, data->rrv);
443    
444                                  pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;          sad = sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);
445            sad += (data->lambda16 * t * sad)>>10;
446    
447                                  iIntra++;          if (data->chroma) sad += ChromaSAD((xc >> 1) + roundtab_79[xc & 0x3],
448                                  if(iIntra >= iLimit)                                                                                  (yc >> 1) + roundtab_79[yc & 0x3], data);
                                         return 1;  
449    
450                                  continue;          if (sad < *(data->iMinSAD)) {
451                    *(data->iMinSAD) = sad;
452                    current->x = x; current->y = y;
453                    *dir = Direction;
454            }
455                          }                          }
456    
457                          if (current->global_flags & XVID_INTER4V)  static void
458    CheckCandidate32I(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
459                          {                          {
460                                  pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  // maximum speed - for P/B/I decision
461                                                         2 * j, 2 * i, mv16.x, mv16.y,          int32_t sad;
                                                            current->motion_flags, current->quant, current->fcode,  
                                                        pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);  
   
                                 pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j + 1, 2 * i, mv16.x, mv16.y,  
                                                            current->motion_flags, current->quant, current->fcode,  
                                                        pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);  
462    
463                                  pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,          if ( (x > data->max_dx) || (x < data->min_dx)
464                                                         2 * j, 2 * i + 1, mv16.x, mv16.y,                  || (y > data->max_dy) || (y < data->min_dy) ) return;
                                                            current->motion_flags, current->quant, current->fcode,  
                                                        pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);  
465    
466                                  pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,          sad = sad32v_c(data->Cur, data->RefP[0] + (x>>1) + (y>>1)*(data->iEdgedWidth),
467                                                         2 * j + 1, 2 * i + 1, mv16.x, mv16.y,                                          data->iEdgedWidth, data->temp+1);
                                                            current->motion_flags, current->quant, current->fcode,  
                                                        pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);  
468    
469                                  sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];          if (sad < *(data->iMinSAD)) {
470                    *(data->iMinSAD) = sad;
471                    data->currentMV[0].x = x; data->currentMV[0].y = y;
472                    *dir = Direction;
473                          }                          }
474            if (data->temp[1] < data->iMinSAD[1]) {
475                    data->iMinSAD[1] = data->temp[1]; data->currentMV[1].x = x; data->currentMV[1].y = y; }
476            if (data->temp[2] < data->iMinSAD[2]) {
477                    data->iMinSAD[2] = data->temp[2]; data->currentMV[2].x = x; data->currentMV[2].y = y; }
478            if (data->temp[3] < data->iMinSAD[3]) {
479                    data->iMinSAD[3] = data->temp[3]; data->currentMV[3].x = x; data->currentMV[3].y = y; }
480            if (data->temp[4] < data->iMinSAD[4]) {
481                    data->iMinSAD[4] = data->temp[4]; data->currentMV[4].x = x; data->currentMV[4].y = y; }
482    
483    }
484    
485                          /* decide: MODE_INTER or MODE_INTER4V  static void
486                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v  CheckCandidateInt(const int xf, const int yf, const int Direction, int * const dir, const SearchData * const data)
                         */  
   
                         if (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE)  
                         {  
                                 if (((current->global_flags & XVID_INTER4V)==0) ||  
                                     (sad16 < (sad8 + (int32_t)(IMV16X16 * current->quant))))  
487                                  {                                  {
488            int32_t sad, xb, yb, xcf, ycf, xcb, ycb;
489            uint32_t t;
490            const uint8_t *ReferenceF, *ReferenceB;
491            VECTOR *current;
492    
493                                          sad8 = sad16;          if ((xf > data->max_dx) || (xf < data->min_dx) ||
494                                          pMB->mode = MODE_INTER;                  (yf > data->max_dy) || (yf < data->min_dy))
495                                          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;                  return;
                                         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  
                                         pMB->mode = MODE_INTER4V;  
                         }  
                         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;  
                         }  
                 }  
496    
497  /*      dprintf("*** AFTER ***", pMBs[0].b_mvs[0].x);          if (!data->qpel_precision) {
498          for (i = 0; i < iHcount; i++)                  ReferenceF = GetReference(xf, yf, data);
499                  for (j = 0; j < iWcount; j++)                  xb = data->currentMV[1].x; yb = data->currentMV[1].y;
500                  {                  ReferenceB = GetReferenceB(xb, yb, 1, data);
501                          dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,                  current = data->currentMV;
502                                  pMBs[j + i * iWcount].mode,                  xcf = xf; ycf = yf;
503                                  pMBs[j + i * iWcount].dquant,                  xcb = xb; ycb = yb;
504                                  pMBs[j + i * iWcount].mvs[0],          } else {
505                                  pMBs[j + i * iWcount].mvs[1],                  ReferenceF = Interpolate16x16qpel(xf, yf, 0, data);
506                                  pMBs[j + i * iWcount].mvs[2],                  xb = data->currentQMV[1].x; yb = data->currentQMV[1].y;
507                                  pMBs[j + i * iWcount].mvs[3],                  current = data->currentQMV;
508                                  pMBs[j + i * iWcount].sad8[0],                  ReferenceB = Interpolate16x16qpel(xb, yb, 1, data);
509                                  pMBs[j + i * iWcount].sad8[1],                  xcf = xf/2; ycf = yf/2;
510                                  pMBs[j + i * iWcount].sad8[2],                  xcb = xb/2; ycb = yb/2;
                                 pMBs[j + i * iWcount].sad8[3],  
                                 pMBs[j + i * iWcount].sad16);  
511                  }                  }
         */  
512    
513          return 0;          t = d_mv_bits(xf, yf, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0)
514  }                          + d_mv_bits(xb, yb, data->bpredMV, data->iFcode, data->qpel^data->qpel_precision, 0);
515    
516  #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
517            sad += (data->lambda16 * t * sad)>>10;
518    
519  #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )          if (data->chroma) sad += ChromaSAD2((xcf >> 1) + roundtab_79[xcf & 0x3],
520                                                                                    (ycf >> 1) + roundtab_79[ycf & 0x3],
521                                                                                    (xcb >> 1) + roundtab_79[xcb & 0x3],
522                                                                                    (ycb >> 1) + roundtab_79[ycb & 0x3], data);
523    
524            if (sad < *(data->iMinSAD)) {
525                    *(data->iMinSAD) = sad;
526                    current->x = xf; current->y = yf;
527                    *dir = Direction;
528            }
529    }
530    
531  #define CHECK_MV16_ZERO {\  static void
532    if ( (0 <= max_dx) && (0 >= min_dx) \  CheckCandidateDirect(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
     && (0 <= max_dy) && (0 >= min_dy) ) \  
   { \  
     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \  
     iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\  
     if (iSAD <= iQuant * 96)    \  
         iSAD -= MV16_00_BIAS; \  
     if (iSAD < iMinSAD) \  
     {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \  
 }  
   
 #define NOCHECK_MV16_CANDIDATE(X,Y) { \  
     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \  
     iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\  
     if (iSAD < iMinSAD) \  
     {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \  
 }  
   
 #define CHECK_MV16_CANDIDATE(X,Y) { \  
   if ( ((X) <= max_dx) && ((X) >= min_dx) \  
     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \  
   { \  
     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \  
     iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\  
     if (iSAD < iMinSAD) \  
     {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \  
 }  
   
 #define CHECK_MV16_CANDIDATE_DIR(X,Y,D) { \  
   if ( ((X) <= max_dx) && ((X) >= min_dx) \  
     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \  
   { \  
     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \  
     iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\  
     if (iSAD < iMinSAD) \  
     {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \  
 }  
   
 #define CHECK_MV16_CANDIDATE_FOUND(X,Y,D) { \  
   if ( ((X) <= max_dx) && ((X) >= min_dx) \  
     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \  
   { \  
     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \  
     iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\  
     if (iSAD < iMinSAD) \  
     {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \  
 }  
   
   
 #define CHECK_MV8_ZERO {\  
   iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \  
   iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\  
   if (iSAD < iMinSAD) \  
   { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \  
 }  
   
 #define NOCHECK_MV8_CANDIDATE(X,Y) \  
   { \  
     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \  
     iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\  
     if (iSAD < iMinSAD) \  
     {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \  
 }  
   
 #define CHECK_MV8_CANDIDATE(X,Y) { \  
   if ( ((X) <= max_dx) && ((X) >= min_dx) \  
     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \  
   { \  
     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \  
     iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\  
     if (iSAD < iMinSAD) \  
     {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \  
 }  
   
 #define CHECK_MV8_CANDIDATE_DIR(X,Y,D) { \  
   if ( ((X) <= max_dx) && ((X) >= min_dx) \  
     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \  
   { \  
     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \  
     iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\  
     if (iSAD < iMinSAD) \  
     {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \  
 }  
   
 #define CHECK_MV8_CANDIDATE_FOUND(X,Y,D) { \  
   if ( ((X) <= max_dx) && ((X) >= min_dx) \  
     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \  
   { \  
     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \  
     iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\  
     if (iSAD < iMinSAD) \  
     {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \  
 }  
   
 /* too slow and not fully functional at the moment */  
 /*  
 int32_t ZeroSearch16(  
                                         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,  
                                         MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV)  
533  {  {
534          const int32_t iEdgedWidth = pParam->edged_width;          int32_t sad = 0, xcf = 0, ycf = 0, xcb = 0, ycb = 0;
535          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          uint32_t k;
536          int32_t iSAD;          const uint8_t *ReferenceF;
537          int32_t pred_x,pred_y;          const uint8_t *ReferenceB;
538            VECTOR mvs, b_mvs;
         get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);  
   
         iSAD = sad16( cur,  
                 get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),  
                 iEdgedWidth, MV_MAX_ERROR);  
         if (iSAD <= iQuant * 96)  
                 iSAD -= MV16_00_BIAS;  
   
         currMV->x = 0;  
         currMV->y = 0;  
         currPMV->x = -pred_x;  
         currPMV->y = -pred_y;  
539    
540          return iSAD;          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
541    
542  }          for (k = 0; k < 4; k++) {
543  */                  mvs.x = data->directmvF[k].x + x;
544                    b_mvs.x = ((x == 0) ?
545                            data->directmvB[k].x
546                            : mvs.x - data->referencemv[k].x);
547    
548  int32_t Diamond16_MainSearch(                  mvs.y = data->directmvF[k].y + y;
549          const uint8_t * const pRef,                  b_mvs.y = ((y == 0) ?
550          const uint8_t * const pRefH,                          data->directmvB[k].y
551          const uint8_t * const pRefV,                          : mvs.y - data->referencemv[k].y);
552          const uint8_t * const pRefHV,  
553          const uint8_t * const cur,                  if ((mvs.x > data->max_dx)   || (mvs.x < data->min_dx)   ||
554          const int x, const int y,                          (mvs.y > data->max_dy)   || (mvs.y < data->min_dy)   ||
555          int32_t startx, int32_t starty,                          (b_mvs.x > data->max_dx) || (b_mvs.x < data->min_dx) ||
556          int32_t iMinSAD,                          (b_mvs.y > data->max_dy) || (b_mvs.y < data->min_dy) )
557          VECTOR * const currMV,                          return;
558          const VECTOR * const pmv,  
559          const int32_t min_dx, const int32_t max_dx,                  if (data->qpel) {
560          const int32_t min_dy, const int32_t max_dy,                          xcf += mvs.x/2; ycf += mvs.y/2;
561          const int32_t iEdgedWidth,                          xcb += b_mvs.x/2; ycb += b_mvs.y/2;
562          const int32_t iDiamondSize,                  } else {
563          const int32_t iFcode,                          xcf += mvs.x; ycf += mvs.y;
564          const int32_t iQuant,                          xcb += b_mvs.x; ycb += b_mvs.y;
565          int iFound)                          mvs.x *= 2; mvs.y *= 2; //we move to qpel precision anyway
566  {                          b_mvs.x *= 2; b_mvs.y *= 2;
 /* Do a diamond search around given starting point, return SAD of best */  
   
         int32_t iDirection=0;  
         int32_t iSAD;  
         VECTOR backupMV;  
         backupMV.x = startx;  
         backupMV.y = starty;  
   
 /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  
   
         CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);  
         CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);  
         CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);  
         CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);  
   
         if (iDirection)  
                 while (!iFound)  
                 {  
                         iFound = 1;  
                         backupMV=*currMV;  
   
                         if ( iDirection != 2)  
                                 CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);  
                         if ( iDirection != 1)  
                                 CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);  
                         if ( iDirection != 4)  
                                 CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);  
                         if ( iDirection != 3)  
                                 CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);  
                 }  
         else  
         {  
                 currMV->x = startx;  
                 currMV->y = starty;  
         }  
         return iMinSAD;  
567  }  }
568    
569  int32_t Square16_MainSearch(                  ReferenceF = Interpolate8x8qpel(mvs.x, mvs.y, k, 0, data);
570                                          const uint8_t * const pRef,                  ReferenceB = Interpolate8x8qpel(b_mvs.x, b_mvs.y, k, 1, data);
                                         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)  
 {  
 /* Do a square search around given starting point, return SAD of best */  
   
         int32_t iDirection=0;  
         int32_t iSAD;  
         VECTOR backupMV;  
         backupMV.x = startx;  
         backupMV.y = starty;  
   
 /* It's one search with full square pattern, and new parts for all following diamonds */  
   
 /*   new direction are extra, so 1-4 is normal diamond  
       537  
       1*2  
       648  
 */  
571    
572          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                  sad += sad8bi(data->Cur + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
573          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                  ReferenceF, ReferenceB, data->iEdgedWidth);
574          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                  if (sad > *(data->iMinSAD)) return;
575          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          }
576    
577          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          sad += (data->lambda16 * d_mv_bits(x, y, zeroMV, 1, 0, 0) * sad)>>10;
         CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
         CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);  
         CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
578    
579            if (data->chroma) sad += ChromaSAD2((xcf >> 3) + roundtab_76[xcf & 0xf],
580                                                                                    (ycf >> 3) + roundtab_76[ycf & 0xf],
581                                                                                    (xcb >> 3) + roundtab_76[xcb & 0xf],
582                                                                                    (ycb >> 3) + roundtab_76[ycb & 0xf], data);
583    
584          if (iDirection)          if (sad < *(data->iMinSAD)) {
585                  while (!iFound)                  *(data->iMinSAD) = sad;
586                  {                  data->currentMV->x = x; data->currentMV->y = y;
587                          iFound = 1;                  *dir = Direction;
588                          backupMV=*currMV;          }
589    }
590    
591                          switch (iDirection)  static void
592    CheckCandidateDirectno4v(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
593                          {                          {
594                                  case 1:          int32_t sad, xcf, ycf, xcb, ycb;
595                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);          const uint8_t *ReferenceF;
596                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          const uint8_t *ReferenceB;
597                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          VECTOR mvs, b_mvs;
                                         break;  
                                 case 2:  
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);  
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
                                         break;  
598    
599                                  case 3:          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);  
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);  
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
                                         break;  
600    
601                                  case 4:          mvs.x = data->directmvF[0].x + x;
602                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          b_mvs.x = ((x == 0) ?
603                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                  data->directmvB[0].x
604                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                  : mvs.x - data->referencemv[0].x);
                                         break;  
605    
606                                  case 5:          mvs.y = data->directmvF[0].y + y;
607                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);          b_mvs.y = ((y == 0) ?
608                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                  data->directmvB[0].y
609                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                  : mvs.y - data->referencemv[0].y);
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);  
                                         break;  
610    
611                                  case 6:          if ( (mvs.x > data->max_dx) || (mvs.x < data->min_dx)
612                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                  || (mvs.y > data->max_dy) || (mvs.y < data->min_dy)
613                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                  || (b_mvs.x > data->max_dx) || (b_mvs.x < data->min_dx)
614                    || (b_mvs.y > data->max_dy) || (b_mvs.y < data->min_dy) ) return;
615    
616                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          if (data->qpel) {
617                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                  xcf = 4*(mvs.x/2); ycf = 4*(mvs.y/2);
618                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                  xcb = 4*(b_mvs.x/2); ycb = 4*(b_mvs.y/2);
619                    ReferenceF = Interpolate16x16qpel(mvs.x, mvs.y, 0, data);
620                    ReferenceB = Interpolate16x16qpel(b_mvs.x, b_mvs.y, 1, data);
621            } else {
622                    xcf = 4*mvs.x; ycf = 4*mvs.y;
623                    xcb = 4*b_mvs.x; ycb = 4*b_mvs.y;
624                    ReferenceF = GetReference(mvs.x, mvs.y, data);
625                    ReferenceB = GetReferenceB(b_mvs.x, b_mvs.y, 1, data);
626            }
627    
628                                          break;          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
629            sad += (data->lambda16 * d_mv_bits(x, y, zeroMV, 1, 0, 0) * sad)>>10;
630    
631                                  case 7:          if (data->chroma) sad += ChromaSAD2((xcf >> 3) + roundtab_76[xcf & 0xf],
632                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                                                                  (ycf >> 3) + roundtab_76[ycf & 0xf],
633                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                  (xcb >> 3) + roundtab_76[xcb & 0xf],
634                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                  (ycb >> 3) + roundtab_76[ycb & 0xf], data);
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);  
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
                                         break;  
635    
636                                  case 8:          if (sad < *(data->iMinSAD)) {
637                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                  *(data->iMinSAD) = sad;
638                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                  data->currentMV->x = x; data->currentMV->y = y;
639                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                  *dir = Direction;
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);  
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
                                         break;  
                         default:  
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);  
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);  
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);  
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);  
   
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);  
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);  
                                         CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
                                         break;  
640                          }                          }
641                  }                  }
642          else  
643    
644    static void
645    CheckCandidateBits16(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
646                  {                  {
                         currMV->x = startx;  
                         currMV->y = starty;  
                 }  
         return iMinSAD;  
 }  
647    
648            int16_t *in = data->dctSpace, *coeff = data->dctSpace + 64;
649            int32_t bits = 0, sum;
650            VECTOR * current;
651            const uint8_t * ptr;
652            int i, cbp = 0, t, xc, yc;
653    
654  int32_t Full16_MainSearch(          if ( (x > data->max_dx) || (x < data->min_dx)
655                                          const uint8_t * const pRef,                  || (y > data->max_dy) || (y < data->min_dy) ) return;
                                         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)  
 {  
         int32_t iSAD;  
         int32_t dx,dy;  
         VECTOR backupMV;  
         backupMV.x = startx;  
         backupMV.y = starty;  
   
         for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)  
                 for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)  
                         NOCHECK_MV16_CANDIDATE(dx,dy);  
656    
657          return iMinSAD;          if (!data->qpel_precision) {
658                    ptr = GetReference(x, y, data);
659                    current = data->currentMV;
660                    xc = x; yc = y;
661            } else { // x and y are in 1/4 precision
662                    ptr = Interpolate16x16qpel(x, y, 0, data);
663                    current = data->currentQMV;
664                    xc = x/2; yc = y/2;
665  }  }
666    
667  int32_t Full8_MainSearch(          for(i = 0; i < 4; i++) {
668                                          const uint8_t * const pRef,                  int s = 8*((i&1) + (i>>1)*data->iEdgedWidth);
669                                          const uint8_t * const pRefH,                  transfer_8to16subro(in, data->Cur + s, ptr + s, data->iEdgedWidth);
670                                          const uint8_t * const pRefV,                  fdct(in);
671                                          const uint8_t * const pRefHV,                  if (data->lambda8 == 0) sum = quant_inter(coeff, in, data->lambda16);
672                                          const uint8_t * const cur,                  else sum = quant4_inter(coeff, in, data->lambda16);
673                                          const int x, const int y,                  if (sum > 0) {
674                                          int32_t startx, int32_t starty,                          cbp |= 1 << (5 - i);
675                                          int32_t iMinSAD,                          bits += data->temp[i] = CodeCoeffInter_CalcBits(coeff, scan_tables[0]);
676                                          VECTOR * const currMV,                  } else data->temp[i] = 0;
                                         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)  
 {  
         int32_t iSAD;  
         int32_t dx,dy;  
         VECTOR backupMV;  
         backupMV.x = startx;  
         backupMV.y = starty;  
   
         for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)  
                 for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)  
                         NOCHECK_MV8_CANDIDATE(dx,dy);  
   
         return iMinSAD;  
677  }  }
678    
679            bits += t = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
680    
681            if (bits < data->iMinSAD[0]) { // there is still a chance, adding chroma
682                    xc = (xc >> 1) + roundtab_79[xc & 0x3];
683                    yc = (yc >> 1) + roundtab_79[yc & 0x3];
684    
685  int32_t Halfpel16_Refine(                  //chroma U
686          const uint8_t * const pRef,                  ptr = interpolate8x8_switch2(data->RefQ + 64, data->RefP[4], 0, 0, xc, yc,  data->iEdgedWidth/2, data->rounding);
687          const uint8_t * const pRefH,                  transfer_8to16subro(in, ptr, data->CurU, data->iEdgedWidth/2);
688          const uint8_t * const pRefV,                  fdct(in);
689          const uint8_t * const pRefHV,                  if (data->lambda8 == 0) sum = quant_inter(coeff, in, data->lambda16);
690          const uint8_t * const cur,                  else sum = quant4_inter(coeff, in, data->lambda16);
691          const int x, const int y,                  if (sum > 0) {
692          VECTOR * const currMV,                          cbp |= 1 << (5 - 4);
693          int32_t iMinSAD,                          bits += CodeCoeffInter_CalcBits(coeff, scan_tables[0]);
694          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) */  
695    
696          int32_t iSAD;                  if (bits < data->iMinSAD[0]) {
697          VECTOR backupMV = *currMV;                          //chroma V
698                            ptr = interpolate8x8_switch2(data->RefQ + 64, data->RefP[5], 0, 0, xc, yc,  data->iEdgedWidth/2, data->rounding);
699                            transfer_8to16subro(in, ptr, data->CurV, data->iEdgedWidth/2);
700                            fdct(in);
701                            if (data->lambda8 == 0) sum = quant_inter(coeff, in, data->lambda16);
702                            else sum = quant4_inter(coeff, in, data->lambda16);
703                            if (sum > 0) {
704                                    cbp |= 1 << (5 - 5);
705                                    bits += CodeCoeffInter_CalcBits(coeff, scan_tables[0]);
706                            }
707                    }
708            }
709    
710          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);          bits += xvid_cbpy_tab[15-(cbp>>2)].len;
711          CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);          bits += mcbpc_inter_tab[(MODE_INTER & 7) | ((cbp & 3) << 3)].len;
         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);  
712    
713          return iMinSAD;          if (bits < data->iMinSAD[0]) {
714                    data->iMinSAD[0] = bits;
715                    current[0].x = x; current[0].y = y;
716                    *dir = Direction;
717  }  }
718    
719  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)          if (data->temp[0] + t < data->iMinSAD[1]) {
720                    data->iMinSAD[1] = data->temp[0] + t; current[1].x = x; current[1].y = y; }
721            if (data->temp[1] < data->iMinSAD[2]) {
722                    data->iMinSAD[2] = data->temp[1]; current[2].x = x; current[2].y = y; }
723            if (data->temp[2] < data->iMinSAD[3]) {
724                    data->iMinSAD[3] = data->temp[2]; current[3].x = x; current[3].y = y; }
725            if (data->temp[3] < data->iMinSAD[4]) {
726                    data->iMinSAD[4] = data->temp[3]; current[4].x = x; current[4].y = y; }
727    
728  int32_t PMVfastSearch16(  }
729                                          const uint8_t * const pRef,  static void
730                                          const uint8_t * const pRefH,  CheckCandidateBits8(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
                                         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)  
731  {  {
     const uint32_t iWcount = pParam->mb_width;  
         const int32_t iWidth = pParam->width;  
         const int32_t iHeight = pParam->height;  
         const int32_t iEdgedWidth = pParam->edged_width;  
732    
733          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          int16_t *in = data->dctSpace, *coeff = data->dctSpace + 64;
734            int32_t sum, bits;
735            VECTOR * current;
736            const uint8_t * ptr;
737            int cbp;
738    
739          int32_t iDiamondSize;          if ( (x > data->max_dx) || (x < data->min_dx)
740                    || (y > data->max_dy) || (y < data->min_dy) ) return;
741    
742          int32_t min_dx;          if (!data->qpel_precision) {
743          int32_t max_dx;                  ptr = GetReference(x, y, data);
744          int32_t min_dy;                  current = data->currentMV;
745          int32_t max_dy;          } else { // x and y are in 1/4 precision
746                    ptr = Interpolate8x8qpel(x, y, 0, 0, data);
747                    current = data->currentQMV;
748            }
749    
750          int32_t iFound;          transfer_8to16subro(in, data->Cur, ptr, data->iEdgedWidth);
751            fdct(in);
752            if (data->lambda8 == 0) sum = quant_inter(coeff, in, data->lambda16);
753            else sum = quant4_inter(coeff, in, data->lambda16);
754            if (sum > 0) {
755                    bits = CodeCoeffInter_CalcBits(coeff, scan_tables[0]);
756                    cbp = 1;
757            } else cbp = bits = 0;
758    
759          VECTOR newMV;          bits += sum = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
         VECTOR backupMV;        /* just for PMVFAST */  
760    
761          VECTOR pmv[4];          if (bits < data->iMinSAD[0]) {
762          int32_t psad[4];                  data->temp[0] = cbp;
763                    data->iMinSAD[0] = bits;
764                    current[0].x = x; current[0].y = y;
765                    *dir = Direction;
766            }
767    }
768    
769          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  /* CHECK_CANDIATE FUNCTIONS END */
         const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;  
770    
771          static int32_t threshA,threshB;  /* MAINSEARCH FUNCTIONS START */
         int32_t bPredEq;  
         int32_t iMinSAD,iSAD;  
772    
773  /* Get maximum range */  static void
774          get_range(&min_dx, &max_dx, &min_dy, &max_dy,  AdvDiamondSearch(int x, int y, const SearchData * const data, int bDirection)
775                    x, y, 16, iWidth, iHeight, iFcode);  {
776    
777  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
778    
779          if (!(MotionFlags & PMV_HALFPEL16 ))          int iDirection;
         { min_dx = EVEN(min_dx);  
         max_dx = EVEN(max_dx);  
         min_dy = EVEN(min_dy);  
         max_dy = EVEN(max_dy);  
         }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */  
780    
781            for(;;) { //forever
782                    iDirection = 0;
783                    if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);
784                    if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);
785                    if (bDirection & 4) CHECK_CANDIDATE(x, y - iDiamondSize, 4);
786                    if (bDirection & 8) CHECK_CANDIDATE(x, y + iDiamondSize, 8);
787    
788          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);                  /* now we're doing diagonal checks near our candidate */
789    
790          if ((x==0) && (y==0) )                  if (iDirection) {               //if anything found
791          {                          bDirection = iDirection;
792                  threshA =  512;                          iDirection = 0;
793                  threshB = 1024;                          x = data->currentMV->x; y = data->currentMV->y;
794                            if (bDirection & 3) {   //our candidate is left or right
795                                    CHECK_CANDIDATE(x, y + iDiamondSize, 8);
796                                    CHECK_CANDIDATE(x, y - iDiamondSize, 4);
797                            } else {                        // what remains here is up or down
798                                    CHECK_CANDIDATE(x + iDiamondSize, y, 2);
799                                    CHECK_CANDIDATE(x - iDiamondSize, y, 1);
800                            }
801    
802                            if (iDirection) {
803                                    bDirection += iDirection;
804                                    x = data->currentMV->x; y = data->currentMV->y;
805                            }
806                    } else {                                //about to quit, eh? not so fast....
807                            switch (bDirection) {
808                            case 2:
809                                    CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
810                                    CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
811                                    break;
812                            case 1:
813                                    CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
814                                    CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
815                                    break;
816                            case 2 + 4:
817                                    CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
818                                    CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
819                                    CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
820                                    break;
821                            case 4:
822                                    CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
823                                    CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
824                                    break;
825                            case 8:
826                                    CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
827                                    CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
828                                    break;
829                            case 1 + 4:
830                                    CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
831                                    CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
832                                    CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
833                                    break;
834                            case 2 + 8:
835                                    CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
836                                    CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
837                                    CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
838                                    break;
839                            case 1 + 8:
840                                    CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
841                                    CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
842                                    CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
843                                    break;
844                            default:                //1+2+4+8 == we didn't find anything at all
845                                    CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
846                                    CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
847                                    CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
848                                    CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
849                                    break;
850                            }
851                            if (!iDirection) break;         //ok, the end. really
852                            bDirection = iDirection;
853                            x = data->currentMV->x; y = data->currentMV->y;
854                    }
855          }          }
         else  
         {  
                 threshA = psad[0];  
                 threshB = threshA+256;  
                 if (threshA< 512) threshA =  512;  
                 if (threshA>1024) threshA = 1024;  
                 if (threshB>1792) threshB = 1792;  
856          }          }
857    
858          iFound=0;  static void
859    SquareSearch(int x, int y, const SearchData * const data, int bDirection)
860  /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  {
861     vector of the median.          int iDirection;
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
862    
863          if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) )          do {
864                  iFound=2;                  iDirection = 0;
865                    if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1+16+64);
866                    if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2+32+128);
867                    if (bDirection & 4) CHECK_CANDIDATE(x, y - iDiamondSize, 4+16+32);
868                    if (bDirection & 8) CHECK_CANDIDATE(x, y + iDiamondSize, 8+64+128);
869                    if (bDirection & 16) CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1+4+16+32+64);
870                    if (bDirection & 32) CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2+4+16+32+128);
871                    if (bDirection & 64) CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1+8+16+64+128);
872                    if (bDirection & 128) CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2+8+32+64+128);
873    
874  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.                  bDirection = iDirection;
875     Otherwise select large Diamond Search.                  x = data->currentMV->x; y = data->currentMV->y;
876  */          } while (iDirection);
877    }
878    
879          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )  static void
880                  iDiamondSize=1; // halfpel!  DiamondSearch(int x, int y, const SearchData * const data, int bDirection)
881          else  {
                 iDiamondSize=2; // halfpel!  
882    
883          if (!(MotionFlags & PMV_HALFPELDIAMOND16) )  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
                 iDiamondSize*=2;  
884    
885  /* Step 4: Calculate SAD around the Median prediction.          int iDirection;
    MinSAD=SAD  
    If Motion Vector equal to Previous frame motion vector  
    and MinSAD<PrevFrmSAD goto Step 10.  
    If SAD<=256 goto Step 10.  
 */  
886    
887            do {
888                    iDirection = 0;
889                    if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);
890                    if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);
891                    if (bDirection & 4) CHECK_CANDIDATE(x, y - iDiamondSize, 4);
892                    if (bDirection & 8) CHECK_CANDIDATE(x, y + iDiamondSize, 8);
893    
894  // Prepare for main loop                  /* now we're doing diagonal checks near our candidate */
895    
896          *currMV=pmv[0];         /* current best := prediction */                  if (iDirection) {               //checking if anything found
897          if (!(MotionFlags & PMV_HALFPEL16 ))                          bDirection = iDirection;
898          {       /* This should NOT be necessary! */                          iDirection = 0;
899                  currMV->x = EVEN(currMV->x);                          x = data->currentMV->x; y = data->currentMV->y;
900                  currMV->y = EVEN(currMV->y);                          if (bDirection & 3) {   //our candidate is left or right
901                                    CHECK_CANDIDATE(x, y + iDiamondSize, 8);
902                                    CHECK_CANDIDATE(x, y - iDiamondSize, 4);
903                            } else {                        // what remains here is up or down
904                                    CHECK_CANDIDATE(x + iDiamondSize, y, 2);
905                                    CHECK_CANDIDATE(x - iDiamondSize, y, 1);
906          }          }
907                            bDirection += iDirection;
908          if (currMV->x > max_dx)                          x = data->currentMV->x; y = data->currentMV->y;
         {  
                 currMV->x=max_dx;  
         }  
         if (currMV->x < min_dx)  
         {  
                 currMV->x=min_dx;  
909          }          }
         if (currMV->y > max_dy)  
         {  
                 currMV->y=max_dy;  
910          }          }
911          if (currMV->y < min_dy)          while (iDirection);
         {  
                 currMV->y=min_dy;  
912          }          }
913    
914          iMinSAD = sad16( cur,  /* MAINSEARCH FUNCTIONS END */
                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),  
                          iEdgedWidth, MV_MAX_ERROR);  
         iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;  
915    
916          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )  static void
917    SubpelRefine(const SearchData * const data)
918          {          {
919    /* Do a half-pel or q-pel refinement */
920            const VECTOR centerMV = data->qpel_precision ? *data->currentQMV : *data->currentMV;
921            int iDirection; //only needed because macro expects it
922    
923                  if (MotionFlags & PMV_QUICKSTOP16)          CHECK_CANDIDATE(centerMV.x, centerMV.y - 1, 0);
924                          goto PMVfast16_Terminate_without_Refine;          CHECK_CANDIDATE(centerMV.x + 1, centerMV.y - 1, 0);
925                  if (MotionFlags & PMV_EARLYSTOP16)          CHECK_CANDIDATE(centerMV.x + 1, centerMV.y, 0);
926                          goto PMVfast16_Terminate_with_Refine;          CHECK_CANDIDATE(centerMV.x + 1, centerMV.y + 1, 0);
927            CHECK_CANDIDATE(centerMV.x, centerMV.y + 1, 0);
928            CHECK_CANDIDATE(centerMV.x - 1, centerMV.y + 1, 0);
929            CHECK_CANDIDATE(centerMV.x - 1, centerMV.y, 0);
930            CHECK_CANDIDATE(centerMV.x - 1, centerMV.y - 1, 0);
931          }          }
932    
933  /*  static __inline int
934     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.  SkipDecisionP(const IMAGE * current, const IMAGE * reference,
935     Also calculate (0,0) but do not subtract offset.                                                          const int x, const int y,
936     Let MinSAD be the smallest SAD up to this point.                                                          const uint32_t stride, const uint32_t iQuant, int rrv)
    If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********  
 */  
937    
938  // (0,0) is always possible  {
939            int offset = (x + y*stride)*8;
940            if(!rrv) {
941                    uint32_t sadC = sad8(current->u + offset,
942                                                    reference->u + offset, stride);
943                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
944                    sadC += sad8(current->v + offset,
945                                                    reference->v + offset, stride);
946                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
947                    return 1;
948    
949          CHECK_MV16_ZERO;          } else {
950                    uint32_t sadC = sad16(current->u + 2*offset,
951                                                    reference->u + 2*offset, stride, 256*4096);
952                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP*4) return 0;
953                    sadC += sad16(current->v + 2*offset,
954                                                    reference->v + 2*offset, stride, 256*4096);
955                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP*4) return 0;
956                    return 1;
957            }
958    }
959    
960  // previous frame MV is always possible  static __inline void
961          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)
962    {
963            pMB->mode = MODE_NOT_CODED;
964            pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = zeroMV;
965            pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] = pMB->qmvs[3] = zeroMV;
966            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = sad;
967    }
968    
969  // left neighbour, if allowed  bool
970          if (x != 0)  MotionEstimation(MBParam * const pParam,
971                                    FRAMEINFO * const current,
972                                    FRAMEINFO * const reference,
973                                    const IMAGE * const pRefH,
974                                    const IMAGE * const pRefV,
975                                    const IMAGE * const pRefHV,
976                                    const uint32_t iLimit)
977          {          {
978                  if (!(MotionFlags & PMV_HALFPEL16 ))          MACROBLOCK *const pMBs = current->mbs;
979                  {       pmv[1].x = EVEN(pmv[1].x);          const IMAGE *const pCurrent = &current->image;
980                  pmv[1].y = EVEN(pmv[1].y);          const IMAGE *const pRef = &reference->image;
981    
982            uint32_t mb_width = pParam->mb_width;
983            uint32_t mb_height = pParam->mb_height;
984            const uint32_t iEdgedWidth = pParam->edged_width;
985            const uint32_t MotionFlags = MakeGoodMotionFlags(current->motion_flags, current->global_flags);
986    
987            uint32_t x, y;
988            uint32_t iIntra = 0;
989            int32_t quant = current->quant, sad00;
990            int skip_thresh = INITIAL_SKIP_THRESH *
991                    (current->global_flags & XVID_REDUCED ? 4:1) *
992                    (current->global_flags & XVID_MODEDECISION_BITS ? 2:1);
993    
994            // some pre-initialized thingies for SearchP
995            int32_t temp[8];
996            VECTOR currentMV[5];
997            VECTOR currentQMV[5];
998            int32_t iMinSAD[5];
999            DECLARE_ALIGNED_MATRIX(dct_space, 2, 64, int16_t, CACHE_LINE);
1000            SearchData Data;
1001            memset(&Data, 0, sizeof(SearchData));
1002            Data.iEdgedWidth = iEdgedWidth;
1003            Data.currentMV = currentMV;
1004            Data.currentQMV = currentQMV;
1005            Data.iMinSAD = iMinSAD;
1006            Data.temp = temp;
1007            Data.iFcode = current->fcode;
1008            Data.rounding = pParam->m_rounding_type;
1009            Data.qpel = pParam->m_quarterpel;
1010            Data.chroma = MotionFlags & PMV_CHROMA16;
1011            Data.rrv = current->global_flags & XVID_REDUCED;
1012            Data.dctSpace = dct_space;
1013    
1014            if ((current->global_flags & XVID_REDUCED)) {
1015                    mb_width = (pParam->width + 31) / 32;
1016                    mb_height = (pParam->height + 31) / 32;
1017                    Data.qpel = 0;
1018            }
1019    
1020            Data.RefQ = pRefV->u; // a good place, also used in MC (for similar purpose)
1021            if (sadInit) (*sadInit) ();
1022    
1023            for (y = 0; y < mb_height; y++) {
1024                    for (x = 0; x < mb_width; x++)  {
1025                            MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
1026    
1027                            if (!Data.rrv) pMB->sad16 =
1028                                    sad16v(pCurrent->y + (x + y * iEdgedWidth) * 16,
1029                                                            pRef->y + (x + y * iEdgedWidth) * 16,
1030                                                            pParam->edged_width, pMB->sad8 );
1031    
1032                            else pMB->sad16 =
1033                                    sad32v_c(pCurrent->y + (x + y * iEdgedWidth) * 32,
1034                                                            pRef->y + (x + y * iEdgedWidth) * 32,
1035                                                            pParam->edged_width, pMB->sad8 );
1036    
1037                            if (Data.chroma) {
1038                                    Data.temp[7] = sad8(pCurrent->u + x*8 + y*(iEdgedWidth/2)*8,
1039                                                                            pRef->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2)
1040                                                                    + sad8(pCurrent->v + (x + y*(iEdgedWidth/2))*8,
1041                                                                            pRef->v + (x + y*(iEdgedWidth/2))*8, iEdgedWidth/2);
1042                                    pMB->sad16 += Data.temp[7];
1043                            }
1044    
1045                            sad00 = pMB->sad16;
1046    
1047                            if (!(current->global_flags & XVID_LUMIMASKING)) {
1048                                    pMB->dquant = NO_CHANGE;
1049                            } else {
1050                                    if (pMB->dquant != NO_CHANGE) {
1051                                            quant += DQtab[pMB->dquant];
1052                                            if (quant > 31) quant = 31;
1053                                            else if (quant < 1) quant = 1;
1054                                    }
1055                            }
1056                            pMB->quant = current->quant;
1057    
1058    //initial skip decision
1059    /* no early skip for GMC (global vector = skip vector is unknown!)  */
1060                            if (!(current->global_flags & XVID_GMC))        { /* no fast SKIP for S(GMC)-VOPs */
1061                                    if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * skip_thresh)
1062                                            if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, iEdgedWidth/2, pMB->quant, Data.rrv)) {
1063                                                    SkipMacroblockP(pMB, sad00);
1064                                                    continue;
1065                  }                  }
                 CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);  
1066          }          }
1067    
1068  // top neighbour, if allowed                          SearchP(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
1069          if (y != 0)                                                  y, MotionFlags, current->global_flags, pMB->quant,
1070          {                                                  &Data, pParam, pMBs, reference->mbs,
1071                  if (!(MotionFlags & PMV_HALFPEL16 ))                                                  current->global_flags & XVID_INTER4V, pMB);
1072                  {       pmv[2].x = EVEN(pmv[2].x);  
1073                  pmv[2].y = EVEN(pmv[2].y);  /* final skip decision, a.k.a. "the vector you found, really that good?" */
1074                            if (!(current->global_flags & XVID_GMC || current->global_flags & XVID_MODEDECISION_BITS)) {
1075                                    if ( pMB->dquant == NO_CHANGE && sad00 < pMB->quant * MAX_SAD00_FOR_SKIP) {
1076                                            if ( (100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH * (Data.rrv ? 4:1) )
1077                                                    if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, iEdgedWidth/2, pMB->quant, Data.rrv))
1078                                                            SkipMacroblockP(pMB, sad00);
1079                                    }
1080                            }
1081                            if (pMB->mode == MODE_INTRA)
1082                                    if (++iIntra > iLimit) return 1;
1083                    }
1084                  }                  }
                 CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);  
1085    
1086  // top right neighbour, if allowed          if (current->global_flags & XVID_GMC )  /* GMC only for S(GMC)-VOPs */
                 if ((uint32_t)x != (iWcount-1))  
1087                  {                  {
1088                          if (!(MotionFlags & PMV_HALFPEL16 ))                  current->warp = GlobalMotionEst( pMBs, pParam, current, reference, pRefH, pRefV, pRefHV);
                         {       pmv[3].x = EVEN(pmv[3].x);  
                         pmv[3].y = EVEN(pmv[3].y);  
                         }  
                         CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);  
1089                  }                  }
1090            return 0;
1091          }          }
1092    
 /* Step 6: If MinSAD <= thresa goto Step 10.  
    If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.  
 */  
1093    
1094          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )  static __inline int
1095    make_mask(const VECTOR * const pmv, const int i)
1096          {          {
1097                  if (MotionFlags & PMV_QUICKSTOP16)          int mask = 255, j;
1098                          goto PMVfast16_Terminate_without_Refine;          for (j = 0; j < i; j++) {
1099                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MVequal(pmv[i], pmv[j])) return 0; // same vector has been checked already
1100                          goto PMVfast16_Terminate_with_Refine;                  if (pmv[i].x == pmv[j].x) {
1101                            if (pmv[i].y == pmv[j].y + iDiamondSize) mask &= ~4;
1102                            else if (pmv[i].y == pmv[j].y - iDiamondSize) mask &= ~8;
1103                    } else
1104                            if (pmv[i].y == pmv[j].y) {
1105                                    if (pmv[i].x == pmv[j].x + iDiamondSize) mask &= ~1;
1106                                    else if (pmv[i].x == pmv[j].x - iDiamondSize) mask &= ~2;
1107                            }
1108            }
1109            return mask;
1110          }          }
1111    
1112    static __inline void
1113    PreparePredictionsP(VECTOR * const pmv, int x, int y, int iWcount,
1114                            int iHcount, const MACROBLOCK * const prevMB, int rrv)
1115    {
1116    
1117  /************ (Diamond Search)  **************/  //this function depends on get_pmvdata which means that it sucks. It should get the predictions by itself
1118  /*          if (rrv) { iWcount /= 2; iHcount /= 2; }
    Step 7: Perform Diamond search, with either the small or large diamond.  
    If Found=2 only examine one Diamond pattern, and afterwards goto step 10  
    Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.  
    If center then goto step 10.  
    Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.  
    Refine by using small diamond and goto step 10.  
 */  
1119    
1120          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          if ( (y != 0) && (x < (iWcount-1)) ) {          // [5] top-right neighbour
1121                    pmv[5].x = EVEN(pmv[3].x);
1122                    pmv[5].y = EVEN(pmv[3].y);
1123            } else pmv[5].x = pmv[5].y = 0;
1124    
1125  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */          if (x != 0) { pmv[3].x = EVEN(pmv[1].x); pmv[3].y = EVEN(pmv[1].y); }// pmv[3] is left neighbour
1126          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          else pmv[3].x = pmv[3].y = 0;
                                           x, y,  
                                           currMV->x, currMV->y, iMinSAD, &newMV,  
                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);  
1127    
1128          if (iSAD < iMinSAD)          if (y != 0) { pmv[4].x = EVEN(pmv[2].x); pmv[4].y = EVEN(pmv[2].y); }// [4] top neighbour
1129          {          else pmv[4].x = pmv[4].y = 0;
                 *currMV = newMV;  
                 iMinSAD = iSAD;  
         }  
1130    
1131          if (MotionFlags & PMV_EXTSEARCH16)          // [1] median prediction
1132          {          pmv[1].x = EVEN(pmv[0].x); pmv[1].y = EVEN(pmv[0].y);
 /* extended: search (up to) two more times: orignal prediction and (0,0) */  
1133    
1134                  if (!(MVequal(pmv[0],backupMV)) )          pmv[0].x = pmv[0].y = 0; // [0] is zero; not used in the loop (checked before) but needed here for make_mask
                 {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,  
                                                           x, y,  
                                                           pmv[0].x, pmv[0].y, iMinSAD, &newMV,  
                                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);  
1135    
1136                  if (iSAD < iMinSAD)          pmv[2].x = EVEN(prevMB->mvs[0].x); // [2] is last frame
1137                  {          pmv[2].y = EVEN(prevMB->mvs[0].y);
                         *currMV = newMV;  
                         iMinSAD = iSAD;  
                 }  
                 }  
1138    
1139                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )          if ((x < iWcount-1) && (y < iHcount-1)) {
1140                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  pmv[6].x = EVEN((prevMB+1+iWcount)->mvs[0].x); //[6] right-down neighbour in last frame
1141                                                            x, y,                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
1142                                                            0, 0, iMinSAD, &newMV,          } else pmv[6].x = pmv[6].y = 0;
                                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);  
1143    
1144                  if (iSAD < iMinSAD)          if (rrv) {
1145                  {                  int i;
1146                          *currMV = newMV;                  for (i = 0; i < 7; i++) {
1147                          iMinSAD = iSAD;                          pmv[i].x = RRV_MV_SCALEUP(pmv[i].x);
1148                            pmv[i].y = RRV_MV_SCALEUP(pmv[i].y);
1149                  }                  }
1150                  }                  }
1151          }          }
1152    
1153  /*  static int
1154     Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.  ModeDecision(const uint32_t iQuant, SearchData * const Data,
1155  */                  int inter4v,
1156                    MACROBLOCK * const pMB,
1157                    const MACROBLOCK * const pMBs,
1158                    const int x, const int y,
1159                    const MBParam * const pParam,
1160                    const uint32_t MotionFlags,
1161                    const uint32_t GlobalFlags)
1162    {
1163    
1164  PMVfast16_Terminate_with_Refine:          int mode = MODE_INTER;
         if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step  
                 iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,  
                                   x, y,  
                                   currMV, iMinSAD,  
                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);  
1165    
1166  PMVfast16_Terminate_without_Refine:          if (!(GlobalFlags & XVID_MODEDECISION_BITS)) { //normal, fast, SAD-based mode decision
1167          currPMV->x = currMV->x - pmv[0].x;                  int sad;
1168          currPMV->y = currMV->y - pmv[0].y;                  int InterBias = MV16_INTER_BIAS;
1169          return iMinSAD;                  if (inter4v == 0 || Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
1170                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant) {
1171                            mode = MODE_INTER;
1172                            sad = Data->iMinSAD[0];
1173                    } else {
1174                            mode = MODE_INTER4V;
1175                            sad = Data->iMinSAD[1] + Data->iMinSAD[2] +
1176                                                    Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant;
1177                            Data->iMinSAD[0] = sad;
1178  }  }
1179    
1180                    /* intra decision */
1181    
1182                    if (iQuant > 8) InterBias += 100 * (iQuant - 8); // to make high quants work
1183                    if (y != 0)
1184                            if ((pMB - pParam->mb_width)->mode == MODE_INTRA ) InterBias -= 80;
1185                    if (x != 0)
1186                            if ((pMB - 1)->mode == MODE_INTRA ) InterBias -= 80;
1187    
1188                    if (Data->chroma) InterBias += 50; // to compensate bigger SAD
1189                    if (Data->rrv) InterBias *= 4;
1190    
1191                    if (InterBias < pMB->sad16) {
1192                            int32_t deviation;
1193                            if (!Data->rrv) deviation = dev16(Data->Cur, Data->iEdgedWidth);
1194                            else deviation = dev16(Data->Cur, Data->iEdgedWidth) +
1195                                    dev16(Data->Cur+8, Data->iEdgedWidth) +
1196                                    dev16(Data->Cur + 8*Data->iEdgedWidth, Data->iEdgedWidth) +
1197                                    dev16(Data->Cur+8+8*Data->iEdgedWidth, Data->iEdgedWidth);
1198    
1199                            if (deviation < (sad - InterBias)) return MODE_INTRA;
 int32_t Diamond8_MainSearch(  
         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)  
 {  
 /* Do a diamond search around given starting point, return SAD of best */  
   
         int32_t iDirection=0;  
         int32_t iSAD;  
         VECTOR backupMV;  
         backupMV.x = startx;  
         backupMV.y = starty;  
   
 /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  
   
         CHECK_MV8_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);  
         CHECK_MV8_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);  
         CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);  
         CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);  
   
         if (iDirection)  
                 while (!iFound)  
                 {  
                         iFound = 1;  
                         backupMV=*currMV;       // since iDirection!=0, this is well defined!  
   
                         if ( iDirection != 2)  
                                 CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);  
                         if ( iDirection != 1)  
                                 CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);  
                         if ( iDirection != 4)  
                                 CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);  
                         if ( iDirection != 3)  
                                 CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);  
                 }  
         else  
         {  
                 currMV->x = startx;  
                 currMV->y = starty;  
         }  
         return iMinSAD;  
1200  }  }
1201                    return mode;
1202    
1203  int32_t Halfpel8_Refine(          } else {
1204          const uint8_t * const pRef,  
1205          const uint8_t * const pRefH,                  int bits, intra, i;
1206          const uint8_t * const pRefV,                  VECTOR backup[5], *v;
1207          const uint8_t * const pRefHV,                  Data->lambda16 = iQuant;
1208          const uint8_t * const cur,                  Data->lambda8 = pParam->m_quant_type;
         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) */  
1209    
1210          int32_t iSAD;                  v = Data->qpel ? Data->currentQMV : Data->currentMV;
1211          VECTOR backupMV = *currMV;                  for (i = 0; i < 5; i++) {
1212                            Data->iMinSAD[i] = 256*4096;
1213                            backup[i] = v[i];
1214                    }
1215    
1216          CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y-1);                  bits = CountMBBitsInter(Data, pMBs, x, y, pParam, MotionFlags);
1217          CHECK_MV8_CANDIDATE(backupMV.x  ,backupMV.y-1);                  if (bits == 0) return MODE_INTER; // quick stop
         CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y-1);  
         CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y);  
         CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y);  
         CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y+1);  
         CHECK_MV8_CANDIDATE(backupMV.x  ,backupMV.y+1);  
         CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y+1);  
1218    
1219          return iMinSAD;                  if (inter4v) {
1220                            int bits_inter4v = CountMBBitsInter4v(Data, pMB, pMBs, x, y, pParam, MotionFlags, backup);
1221                            if (bits_inter4v < bits) { Data->iMinSAD[0] = bits = bits_inter4v; mode = MODE_INTER4V; }
1222  }  }
1223    
1224                    intra = CountMBBitsIntra(Data);
1225    
1226  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)                  if (intra < bits) { *Data->iMinSAD = bits = intra; return MODE_INTRA; }
1227    
1228  int32_t PMVfastSearch8(                  return mode;
1229                                          const uint8_t * const pRef,          }
1230    }
1231    
1232    static void
1233    SearchP(const IMAGE * const pRef,
1234                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1235                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1236                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1237                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1238                                          const int x, const int y,                  const int x,
1239                                          const int start_x, const int start_y,                  const int y,
1240                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1241                    const uint32_t GlobalFlags,
1242                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1243                                          const uint32_t iFcode,                  SearchData * const Data,
1244                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1245                                          const MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
1246                                          const MACROBLOCK * const prevMBs,                                          const MACROBLOCK * const prevMBs,
1247                                          VECTOR * const currMV,                  int inter4v,
1248                                          VECTOR * const currPMV)                  MACROBLOCK * const pMB)
1249  {  {
     const uint32_t iWcount = pParam->mb_width;  
         const int32_t iWidth = pParam->width;  
         const int32_t iHeight = pParam->height;  
         const int32_t iEdgedWidth = pParam->edged_width;  
1250    
1251          const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;          int i, iDirection = 255, mask, threshA;
1252            VECTOR pmv[7];
1253    
1254            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1255                                                    pParam->width, pParam->height, Data->iFcode - Data->qpel, 0, Data->rrv);
1256    
1257            get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);
1258    
1259            Data->temp[5] = Data->temp[6] = 0; // chroma-sad cache
1260            i = Data->rrv ? 2 : 1;
1261            Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16*i;
1262            Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
1263            Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
1264    
1265            Data->RefP[0] = pRef->y + (x + Data->iEdgedWidth*y) * 16*i;
1266            Data->RefP[2] = pRefH + (x + Data->iEdgedWidth*y) * 16*i;
1267            Data->RefP[1] = pRefV + (x + Data->iEdgedWidth*y) * 16*i;
1268            Data->RefP[3] = pRefHV + (x + Data->iEdgedWidth*y) * 16*i;
1269            Data->RefP[4] = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
1270            Data->RefP[5] = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
1271    
1272            Data->lambda16 = lambda_vec16[iQuant];
1273            Data->lambda8 = lambda_vec8[iQuant];
1274            Data->qpel_precision = 0;
1275    
1276            if (pMB->dquant != NO_CHANGE) inter4v = 0;
1277    
1278            memset(Data->currentMV, 0, 5*sizeof(VECTOR));
1279    
1280            if (Data->qpel) Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1281            else Data->predMV = pmv[0];
1282    
1283            i = d_mv_bits(0, 0, Data->predMV, Data->iFcode, 0, 0);
1284            Data->iMinSAD[0] = pMB->sad16 + ((Data->lambda16 * i * pMB->sad16)>>10);
1285            Data->iMinSAD[1] = pMB->sad8[0] + ((Data->lambda8 * i * (pMB->sad8[0]+NEIGH_8X8_BIAS)) >> 10);
1286            Data->iMinSAD[2] = pMB->sad8[1];
1287            Data->iMinSAD[3] = pMB->sad8[2];
1288            Data->iMinSAD[4] = pMB->sad8[3];
1289    
1290            if ((!(GlobalFlags & XVID_MODEDECISION_BITS)) || (x | y)) {
1291                    threshA = Data->temp[0]; // that's where we keep this SAD atm
1292                    if (threshA < 512) threshA = 512;
1293                    else if (threshA > 1024) threshA = 1024;
1294            } else
1295                    threshA = 512;
1296    
1297            PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,
1298                                            prevMBs + x + y * pParam->mb_width, Data->rrv);
1299    
1300            if (!Data->rrv) {
1301                    if (inter4v | Data->chroma) CheckCandidate = CheckCandidate16;
1302                            else CheckCandidate = CheckCandidate16no4v; //for extra speed
1303            } else CheckCandidate = CheckCandidate32;
1304    
1305    /* main loop. checking all predictions (but first, which is 0,0 and has been checked in MotionEstimation())*/
1306    
1307            for (i = 1; i < 7; i++) {
1308                    if (!(mask = make_mask(pmv, i)) ) continue;
1309                    CheckCandidate(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1310                    if (Data->iMinSAD[0] <= threshA) break;
1311            }
1312    
1313            if ((Data->iMinSAD[0] <= threshA) ||
1314                            (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
1315                            (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {
1316                    if (!(GlobalFlags & XVID_MODEDECISION_BITS)) inter4v = 0;       }
1317            else {
1318    
1319                    MainSearchFunc * MainSearchPtr;
1320                    if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
1321                    else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1322                            else MainSearchPtr = DiamondSearch;
1323    
1324                    MainSearchPtr(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1325    
1326    /* extended search, diamond starting in 0,0 and in prediction.
1327            note that this search is/might be done in halfpel positions,
1328            which makes it more different than the diamond above */
1329    
1330                    if (MotionFlags & PMV_EXTSEARCH16) {
1331                            int32_t bSAD;
1332                            VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
1333                            if (Data->rrv) {
1334                                    startMV.x = RRV_MV_SCALEUP(startMV.x);
1335                                    startMV.y = RRV_MV_SCALEUP(startMV.y);
1336                            }
1337                            if (!(MVequal(startMV, backupMV))) {
1338                                    bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1339    
1340                                    CheckCandidate(startMV.x, startMV.y, 255, &iDirection, Data);
1341                                    MainSearchPtr(startMV.x, startMV.y, Data, 255);
1342                                    if (bSAD < Data->iMinSAD[0]) {
1343                                            Data->currentMV[0] = backupMV;
1344                                            Data->iMinSAD[0] = bSAD; }
1345                            }
1346    
1347                            backupMV = Data->currentMV[0];
1348                            startMV.x = startMV.y = 1;
1349                            if (!(MVequal(startMV, backupMV))) {
1350                                    bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1351    
1352                                    CheckCandidate(startMV.x, startMV.y, 255, &iDirection, Data);
1353                                    MainSearchPtr(startMV.x, startMV.y, Data, 255);
1354                                    if (bSAD < Data->iMinSAD[0]) {
1355                                            Data->currentMV[0] = backupMV;
1356                                            Data->iMinSAD[0] = bSAD; }
1357                            }
1358                    }
1359            }
1360    
1361            if (MotionFlags & PMV_HALFPELREFINE16)
1362                    SubpelRefine(Data);
1363    
1364          int32_t iDiamondSize;          for(i = 0; i < 5; i++) {
1365                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1366                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1367            }
1368    
1369          int32_t min_dx;          if (MotionFlags & PMV_QUARTERPELREFINE16) {
         int32_t max_dx;  
         int32_t min_dy;  
         int32_t max_dy;  
1370    
1371          VECTOR pmv[4];                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1372          int32_t psad[4];                                  pParam->width, pParam->height, Data->iFcode, 1, 0);
1373          VECTOR newMV;                  Data->qpel_precision = 1;
1374          VECTOR backupMV;                  SubpelRefine(Data);
1375            }
1376    
1377          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;          if ((!(GlobalFlags & XVID_MODEDECISION_BITS)) && (Data->iMinSAD[0] < (int32_t)iQuant * 30)) inter4v = 0;
         const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;  
1378    
1379          static int32_t threshA,threshB;          if (inter4v) {
1380          int32_t iFound,bPredEq;                  SearchData Data8;
1381          int32_t iMinSAD,iSAD;                  memcpy(&Data8, Data, sizeof(SearchData)); //quick copy of common data
1382    
1383          int32_t iSubBlock = ((y&1)<<1) + (x&1);                  Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1384                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1385                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1386                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1387    
1388  /* Get maximum range */                  if ((Data->chroma) && (!(GlobalFlags & XVID_MODEDECISION_BITS))) {
1389          get_range(&min_dx, &max_dx, &min_dy, &max_dy,                          // chroma is only used for comparsion to INTER. if the comparsion will be done in BITS domain, there is no reason to compute it
1390                    x, y, 8, iWidth, iHeight, iFcode);                          int sumx = 0, sumy = 0;
1391                            const int div = Data->qpel ? 2 : 1;
1392                            const VECTOR * const mv = Data->qpel ? pMB->qmvs : pMB->mvs;
1393    
1394  /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */                          for (i = 0; i < 4; i++) {
1395                                    sumx += mv[i].x / div;
1396                                    sumy += mv[i].y / div;
1397                            }
1398    
1399          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))                          Data->iMinSAD[1] += ChromaSAD(  (sumx >> 3) + roundtab_76[sumx & 0xf],
1400          { min_dx = EVEN(min_dx);                                                                                          (sumy >> 3) + roundtab_76[sumy & 0xf], Data);
1401          max_dx = EVEN(max_dx);                  }
1402          min_dy = EVEN(min_dy);          }
         max_dy = EVEN(max_dy);  
         }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */  
1403    
1404            inter4v = ModeDecision(iQuant, Data, inter4v, pMB, pMBs, x, y, pParam, MotionFlags, GlobalFlags);
1405    
1406          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          if (Data->rrv) {
1407                            Data->currentMV[0].x = RRV_MV_SCALEDOWN(Data->currentMV[0].x);
1408                            Data->currentMV[0].y = RRV_MV_SCALEDOWN(Data->currentMV[0].y);
1409            }
1410    
1411          if ((x==0) && (y==0) )          if (inter4v == MODE_INTER) {
1412          {                  pMB->mode = MODE_INTER;
1413                  threshA =  512/4;                  pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1414                  threshB = 1024/4;                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = Data->iMinSAD[0];
1415    
1416                    if(Data->qpel) {
1417                            pMB->qmvs[0] = pMB->qmvs[1]
1418                                    = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1419                            pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predMV.x;
1420                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predMV.y;
1421                    } else {
1422                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1423                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1424          }          }
1425          else  
1426          {          } else if (inter4v == MODE_INTER4V) {
1427                  threshA = psad[0]/4;                    /* good estimate */                  pMB->mode = MODE_INTER4V;
1428                  threshB = threshA+256/4;                  pMB->sad16 = Data->iMinSAD[0];
1429                  if (threshA< 512/4) threshA =  512/4;          } else { // INTRA mode
1430                  if (threshA>1024/4) threshA = 1024/4;                  SkipMacroblockP(pMB, 0); // not skip, but similar enough
1431                  if (threshB>1792/4) threshB = 1792/4;                  pMB->mode = MODE_INTRA;
1432          }          }
1433    
1434          iFound=0;  }
   
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
1435    
1436          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )  static void
1437                  iFound=2;  Search8(const SearchData * const OldData,
1438                    const int x, const int y,
1439                    const uint32_t MotionFlags,
1440                    const MBParam * const pParam,
1441                    MACROBLOCK * const pMB,
1442                    const MACROBLOCK * const pMBs,
1443                    const int block,
1444                    SearchData * const Data)
1445    {
1446            int i = 0;
1447            Data->iMinSAD = OldData->iMinSAD + 1 + block;
1448            Data->currentMV = OldData->currentMV + 1 + block;
1449            Data->currentQMV = OldData->currentQMV + 1 + block;
1450    
1451  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.          if(Data->qpel) {
1452     Otherwise select large Diamond Search.                  Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2, y/2, block);
1453  */                  if (block != 0) i = d_mv_bits(  Data->currentQMV->x, Data->currentQMV->y,
1454                                                                                    Data->predMV, Data->iFcode, 0, 0);
1455            } else {
1456                    Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2, y/2, block);
1457                    if (block != 0) i = d_mv_bits(  Data->currentMV->x, Data->currentMV->y,
1458                                                                                    Data->predMV, Data->iFcode, 0, Data->rrv);
1459            }
1460    
1461          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )          *(Data->iMinSAD) += (Data->lambda8 * i * (*Data->iMinSAD + NEIGH_8X8_BIAS))>>10;
                 iDiamondSize=1; // 1 halfpel!  
         else  
                 iDiamondSize=2; // 2 halfpel = 1 full pixel!  
1462    
1463          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8|PMV_QUARTERPELREFINE8)) {
                 iDiamondSize*=2;  
1464    
1465  /* Step 4: Calculate SAD around the Median prediction.                  if (Data->rrv) i = 16; else i = 8;
    MinSAD=SAD  
    If Motion Vector equal to Previous frame motion vector  
    and MinSAD<PrevFrmSAD goto Step 10.  
    If SAD<=256 goto Step 10.  
 */  
1466    
1467                    Data->RefP[0] = OldData->RefP[0] + i * ((block&1) + Data->iEdgedWidth*(block>>1));
1468                    Data->RefP[1] = OldData->RefP[1] + i * ((block&1) + Data->iEdgedWidth*(block>>1));
1469                    Data->RefP[2] = OldData->RefP[2] + i * ((block&1) + Data->iEdgedWidth*(block>>1));
1470                    Data->RefP[3] = OldData->RefP[3] + i * ((block&1) + Data->iEdgedWidth*(block>>1));
1471    
1472  // Prepare for main loop                  Data->Cur = OldData->Cur + i * ((block&1) + Data->iEdgedWidth*(block>>1));
1473                    Data->qpel_precision = 0;
1474    
1475          currMV->x=start_x;              /* start with mv16 */                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1476          currMV->y=start_y;                                          pParam->width, pParam->height, Data->iFcode - Data->qpel, 0, Data->rrv);
1477    
1478          iMinSAD = sad8( cur,                  if (!Data->rrv) CheckCandidate = CheckCandidate8;
1479                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  else CheckCandidate = CheckCandidate16no4v;
                         iEdgedWidth);  
         iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;  
1480    
1481          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )                  if (MotionFlags & PMV_EXTSEARCH8 && (!(MotionFlags & EXTSEARCH_BITS))) {
1482          {                          int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
                 if (MotionFlags & PMV_QUICKSTOP16)  
                         goto PMVfast8_Terminate_without_Refine;  
                 if (MotionFlags & PMV_EARLYSTOP16)  
                         goto PMVfast8_Terminate_with_Refine;  
         }  
1483    
1484                            MainSearchFunc *MainSearchPtr;
1485                            if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1486                                    else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1487                                            else MainSearchPtr = DiamondSearch;
1488    
1489  /*                          MainSearchPtr(Data->currentMV->x, Data->currentMV->y, Data, 255);
    Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.  
    Also calculate (0,0) but do not subtract offset.  
    Let MinSAD be the smallest SAD up to this point.  
    If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********  
 */  
1490    
1491  // the prediction might be even better than mv16                          if(*(Data->iMinSAD) < temp_sad) {
1492          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);                                          Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1493                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1494                            }
1495                    }
1496    
1497  // (0,0) is always possible                  if (MotionFlags & PMV_HALFPELREFINE8) {
1498          CHECK_MV8_ZERO;                          int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1499    
1500  // previous frame MV is always possible                          SubpelRefine(Data); // perform halfpel refine of current best vector
         CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);  
1501    
1502  // left neighbour, if allowed                          if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1503          if (psad[1] != MV_MAX_ERROR)                                  Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1504          {                                  Data->currentQMV->y = 2 * Data->currentMV->y;
                 if (!(MotionFlags & PMV_HALFPEL8 ))  
                 {       pmv[1].x = EVEN(pmv[1].x);  
                 pmv[1].y = EVEN(pmv[1].y);  
1505                  }                  }
                 CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);  
         }  
   
 // top neighbour, if allowed  
         if (psad[2] != MV_MAX_ERROR)  
         {  
                 if (!(MotionFlags & PMV_HALFPEL8 ))  
                 {       pmv[2].x = EVEN(pmv[2].x);  
                 pmv[2].y = EVEN(pmv[2].y);  
1506                  }                  }
                 CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);  
1507    
1508  // top right neighbour, if allowed                  if (Data->qpel && MotionFlags & PMV_QUARTERPELREFINE8) {
1509                  if (psad[3] != MV_MAX_ERROR)                                  Data->qpel_precision = 1;
1510                  {                                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1511                          if (!(MotionFlags & PMV_HALFPEL8 ))                                          pParam->width, pParam->height, Data->iFcode, 1, 0);
1512                          {       pmv[3].x = EVEN(pmv[3].x);                                  SubpelRefine(Data);
                         pmv[3].y = EVEN(pmv[3].y);  
                         }  
                         CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);  
1513                  }                  }
1514          }          }
1515    
1516  /* Step 6: If MinSAD <= thresa goto Step 10.          if (Data->rrv) {
1517     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.                          Data->currentMV->x = RRV_MV_SCALEDOWN(Data->currentMV->x);
1518  */                          Data->currentMV->y = RRV_MV_SCALEDOWN(Data->currentMV->y);
1519            }
1520    
1521          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if(Data->qpel) {
1522          {                  pMB->pmvs[block].x = Data->currentQMV->x - Data->predMV.x;
1523                  if (MotionFlags & PMV_QUICKSTOP16)                  pMB->pmvs[block].y = Data->currentQMV->y - Data->predMV.y;
1524                          goto PMVfast8_Terminate_without_Refine;                  pMB->qmvs[block] = *Data->currentQMV;
1525                  if (MotionFlags & PMV_EARLYSTOP16)          } else {
1526                          goto PMVfast8_Terminate_with_Refine;                  pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1527          }                  pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1528            }
 /************ (Diamond Search)  **************/  
 /*  
    Step 7: Perform Diamond search, with either the small or large diamond.  
    If Found=2 only examine one Diamond pattern, and afterwards goto step 10  
    Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.  
    If center then goto step 10.  
    Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.  
    Refine by using small diamond and goto step 10.  
 */  
1529    
1530          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          pMB->mvs[block] = *Data->currentMV;
1531            pMB->sad8[block] = 4 * *Data->iMinSAD;
1532    }
1533    
1534  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* motion estimation for B-frames */
         iSAD = Diamond8_MainSearch(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, iFound);  
1535    
1536          if (iSAD < iMinSAD)  static __inline VECTOR
1537    ChoosePred(const MACROBLOCK * const pMB, const uint32_t mode)
1538          {          {
1539                  *currMV = newMV;  /* the stupidiest function ever */
1540                  iMinSAD = iSAD;          return (mode == MODE_FORWARD ? pMB->mvs[0] : pMB->b_mvs[0]);
1541          }          }
1542    
1543          if (MotionFlags & PMV_EXTSEARCH8)  static void __inline
1544          {  PreparePredictionsBF(VECTOR * const pmv, const int x, const int y,
1545  /* extended: search (up to) two more times: orignal prediction and (0,0) */                                                          const uint32_t iWcount,
1546                                                            const MACROBLOCK * const pMB,
1547                  if (!(MVequal(pmv[0],backupMV)) )                                                          const uint32_t mode_curr)
                 {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,  
                                                           x, y,  
                                                           pmv[0].x, pmv[0].y, iMinSAD, &newMV,  
                                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);  
   
                 if (iSAD < iMinSAD)  
1548                  {                  {
                         *currMV = newMV;  
                         iMinSAD = iSAD;  
                 }  
                 }  
1549    
1550                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )          // [0] is prediction
1551                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          pmv[0].x = EVEN(pmv[0].x); pmv[0].y = EVEN(pmv[0].y);
                                                           x, y,  
                                                           0, 0, iMinSAD, &newMV,  
                                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);  
1552    
1553                  if (iSAD < iMinSAD)          pmv[1].x = pmv[1].y = 0; // [1] is zero
                 {  
                         *currMV = newMV;  
                         iMinSAD = iSAD;  
                 }  
                 }  
         }  
1554    
1555  /* Step 10: The motion vector is chosen according to the block corresponding to MinSAD.          pmv[2] = ChoosePred(pMB, mode_curr);
1556     By performing an optional local half-pixel search, we can refine this result even further.          pmv[2].x = EVEN(pmv[2].x); pmv[2].y = EVEN(pmv[2].y);
 */  
1557    
1558  PMVfast8_Terminate_with_Refine:          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour
1559          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);
1560                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  pmv[3].x = EVEN(pmv[3].x); pmv[3].y = EVEN(pmv[3].y);
1561                                                   x, y,          } else pmv[3].x = pmv[3].y = 0;
                                                  currMV, iMinSAD,  
                                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);  
1562    
1563            if (y != 0) {
1564                    pmv[4] = ChoosePred(pMB-iWcount, mode_curr);
1565                    pmv[4].x = EVEN(pmv[4].x); pmv[4].y = EVEN(pmv[4].y);
1566            } else pmv[4].x = pmv[4].y = 0;
1567    
1568  PMVfast8_Terminate_without_Refine:          if (x != 0) {
1569          currPMV->x = currMV->x - pmv[0].x;                  pmv[5] = ChoosePred(pMB-1, mode_curr);
1570          currPMV->y = currMV->y - pmv[0].y;                  pmv[5].x = EVEN(pmv[5].x); pmv[5].y = EVEN(pmv[5].y);
1571            } else pmv[5].x = pmv[5].y = 0;
1572    
1573          return iMinSAD;          if (x != 0 && y != 0) {
1574                    pmv[6] = ChoosePred(pMB-1-iWcount, mode_curr);
1575                    pmv[6].x = EVEN(pmv[6].x); pmv[6].y = EVEN(pmv[6].y);
1576            } else pmv[6].x = pmv[6].y = 0;
1577  }  }
1578    
1579  int32_t EPZSSearch16(  
1580                                          const uint8_t * const pRef,  /* search backward or forward */
1581    static void
1582    SearchBF(       const IMAGE * const pRef,
1583                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1584                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1585                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1586                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1587                                          const int x, const int y,                                          const int x, const int y,
1588                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
                                         const uint32_t iQuant,  
1589                                          const uint32_t iFcode,                                          const uint32_t iFcode,
1590                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1591                                          const MACROBLOCK * const pMBs,                          MACROBLOCK * const pMB,
1592                                          const MACROBLOCK * const prevMBs,                          const VECTOR * const predMV,
1593                                          VECTOR * const currMV,                          int32_t * const best_sad,
1594                                          VECTOR * const currPMV)                          const int32_t mode_current,
1595                            SearchData * const Data)
1596  {  {
     const uint32_t iWcount = pParam->mb_width;  
     const uint32_t iHcount = pParam->mb_height;  
   
         const int32_t iWidth = pParam->width;  
         const int32_t iHeight = pParam->height;  
         const int32_t iEdgedWidth = pParam->edged_width;  
1597    
1598          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          int i, iDirection = 255, mask;
1599            VECTOR pmv[7];
1600            MainSearchFunc *MainSearchPtr;
1601            *Data->iMinSAD = MV_MAX_ERROR;
1602            Data->iFcode = iFcode;
1603            Data->qpel_precision = 0;
1604            Data->temp[5] = Data->temp[6] = Data->temp[7] = 256*4096; // reset chroma-sad cache
1605    
1606          int32_t min_dx;          Data->RefP[0] = pRef->y + (x + Data->iEdgedWidth*y) * 16;
1607          int32_t max_dx;          Data->RefP[2] = pRefH + (x + Data->iEdgedWidth*y) * 16;
1608          int32_t min_dy;          Data->RefP[1] = pRefV + (x + Data->iEdgedWidth*y) * 16;
1609          int32_t max_dy;          Data->RefP[3] = pRefHV + (x + Data->iEdgedWidth*y) * 16;
1610            Data->RefP[4] = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1611            Data->RefP[5] = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1612    
1613          VECTOR newMV;          Data->predMV = *predMV;
         VECTOR backupMV;  
1614    
1615          VECTOR pmv[4];          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1616          int32_t psad[8];                                  pParam->width, pParam->height, iFcode - Data->qpel, 0, 0);
1617    
1618          static MACROBLOCK * oldMBs = NULL;          pmv[0] = Data->predMV;
1619          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;          if (Data->qpel) { pmv[0].x /= 2; pmv[0].y /= 2; }
         const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;  
         MACROBLOCK * oldMB = NULL;  
1620    
1621          static int32_t thresh2;          PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
         int32_t bPredEq;  
         int32_t iMinSAD,iSAD=9999;  
1622    
1623          MainSearch16FuncPtr EPZSMainSearchPtr;          Data->currentMV->x = Data->currentMV->y = 0;
1624            CheckCandidate = CheckCandidate16no4v;
1625    
1626          if (oldMBs == NULL)  // main loop. checking all predictions
1627          {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));          for (i = 0; i < 7; i++) {
1628                  fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));                  if (!(mask = make_mask(pmv, i)) ) continue;
1629                    CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1630          }          }
         oldMB = oldMBs + x + y * iWcount;  
1631    
1632  /* Get maximum range */          if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
1633          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1634                          x, y, 16, iWidth, iHeight, iFcode);                  else MainSearchPtr = DiamondSearch;
1635    
1636  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */          MainSearchPtr(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1637    
1638          if (!(MotionFlags & PMV_HALFPEL16 ))          SubpelRefine(Data);
         { min_dx = EVEN(min_dx);  
           max_dx = EVEN(max_dx);  
           min_dy = EVEN(min_dy);  
           max_dy = EVEN(max_dy);  
         }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */  
1639    
1640          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          if (Data->qpel && *Data->iMinSAD < *best_sad + 300) {
1641                    Data->currentQMV->x = 2*Data->currentMV->x;
1642                    Data->currentQMV->y = 2*Data->currentMV->y;
1643                    Data->qpel_precision = 1;
1644                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1645                                            pParam->width, pParam->height, iFcode, 1, 0);
1646                    SubpelRefine(Data);
1647            }
1648    
1649  /* Step 4: Calculate SAD around the Median prediction.  // three bits are needed to code backward mode. four for forward
         MinSAD=SAD  
         If Motion Vector equal to Previous frame motion vector  
                 and MinSAD<PrevFrmSAD goto Step 10.  
         If SAD<=256 goto Step 10.  
 */  
1650    
1651  // Prepare for main loop          if (mode_current == MODE_FORWARD) *Data->iMinSAD += 4 * Data->lambda16;
1652            else *Data->iMinSAD += 3 * Data->lambda16;
1653    
1654          *currMV=pmv[0];         /* current best := median prediction */          if (*Data->iMinSAD < *best_sad) {
1655          if (!(MotionFlags & PMV_HALFPEL16))                  *best_sad = *Data->iMinSAD;
1656          {                  pMB->mode = mode_current;
1657                  currMV->x = EVEN(currMV->x);                  if (Data->qpel) {
1658                  currMV->y = EVEN(currMV->y);                          pMB->pmvs[0].x = Data->currentQMV->x - predMV->x;
1659                            pMB->pmvs[0].y = Data->currentQMV->y - predMV->y;
1660                            if (mode_current == MODE_FORWARD)
1661                                    pMB->qmvs[0] = *Data->currentQMV;
1662                            else
1663                                    pMB->b_qmvs[0] = *Data->currentQMV;
1664                    } else {
1665                            pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1666                            pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1667                    }
1668                    if (mode_current == MODE_FORWARD) pMB->mvs[0] = *Data->currentMV;
1669                    else pMB->b_mvs[0] = *Data->currentMV;
1670            }
1671    
1672            if (mode_current == MODE_FORWARD) *(Data->currentMV+2) = *Data->currentMV;
1673            else *(Data->currentMV+1) = *Data->currentMV; //we store currmv for interpolate search
1674    }
1675    
1676    static void
1677    SkipDecisionB(const IMAGE * const pCur,
1678                                    const IMAGE * const f_Ref,
1679                                    const IMAGE * const b_Ref,
1680                                    MACROBLOCK * const pMB,
1681                                    const uint32_t x, const uint32_t y,
1682                                    const SearchData * const Data)
1683    {
1684            int dx = 0, dy = 0, b_dx = 0, b_dy = 0;
1685            int32_t sum;
1686            const int div = 1 + Data->qpel;
1687            int k;
1688            const uint32_t stride = Data->iEdgedWidth/2;
1689    //this is not full chroma compensation, only it's fullpel approximation. should work though
1690    
1691            for (k = 0; k < 4; k++) {
1692                    dy += Data->directmvF[k].y / div;
1693                    dx += Data->directmvF[k].x / div;
1694                    b_dy += Data->directmvB[k].y / div;
1695                    b_dx += Data->directmvB[k].x / div;
1696            }
1697    
1698            dy = (dy >> 3) + roundtab_76[dy & 0xf];
1699            dx = (dx >> 3) + roundtab_76[dx & 0xf];
1700            b_dy = (b_dy >> 3) + roundtab_76[b_dy & 0xf];
1701            b_dx = (b_dx >> 3) + roundtab_76[b_dx & 0xf];
1702    
1703            sum = sad8bi(pCur->u + 8 * x + 8 * y * stride,
1704                                            f_Ref->u + (y*8 + dy/2) * stride + x*8 + dx/2,
1705                                            b_Ref->u + (y*8 + b_dy/2) * stride + x*8 + b_dx/2,
1706                                            stride);
1707    
1708            if (sum >= 2 * MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) return; //no skip
1709    
1710            sum += sad8bi(pCur->v + 8*x + 8 * y * stride,
1711                                            f_Ref->v + (y*8 + dy/2) * stride + x*8 + dx/2,
1712                                            b_Ref->v + (y*8 + b_dy/2) * stride + x*8 + b_dx/2,
1713                                            stride);
1714    
1715            if (sum < 2 * MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) {
1716                    pMB->mode = MODE_DIRECT_NONE_MV; //skipped
1717                    for (k = 0; k < 4; k++) {
1718                            pMB->qmvs[k] = pMB->mvs[k];
1719                            pMB->b_qmvs[k] = pMB->b_mvs[k];
1720                    }
1721            }
1722    }
1723    
1724    static __inline uint32_t
1725    SearchDirect(const IMAGE * const f_Ref,
1726                                    const uint8_t * const f_RefH,
1727                                    const uint8_t * const f_RefV,
1728                                    const uint8_t * const f_RefHV,
1729                                    const IMAGE * const b_Ref,
1730                                    const uint8_t * const b_RefH,
1731                                    const uint8_t * const b_RefV,
1732                                    const uint8_t * const b_RefHV,
1733                                    const IMAGE * const pCur,
1734                                    const int x, const int y,
1735                                    const uint32_t MotionFlags,
1736                                    const int32_t TRB, const int32_t TRD,
1737                                    const MBParam * const pParam,
1738                                    MACROBLOCK * const pMB,
1739                                    const MACROBLOCK * const b_mb,
1740                                    int32_t * const best_sad,
1741                                    SearchData * const Data)
1742    
1743    {
1744            int32_t skip_sad;
1745            int k = (x + Data->iEdgedWidth*y) * 16;
1746            MainSearchFunc *MainSearchPtr;
1747    
1748            *Data->iMinSAD = 256*4096;
1749            Data->RefP[0] = f_Ref->y + k;
1750            Data->RefP[2] = f_RefH + k;
1751            Data->RefP[1] = f_RefV + k;
1752            Data->RefP[3] = f_RefHV + k;
1753            Data->b_RefP[0] = b_Ref->y + k;
1754            Data->b_RefP[2] = b_RefH + k;
1755            Data->b_RefP[1] = b_RefV + k;
1756            Data->b_RefP[3] = b_RefHV + k;
1757            Data->RefP[4] = f_Ref->u + (x + (Data->iEdgedWidth/2) * y) * 8;
1758            Data->RefP[5] = f_Ref->v + (x + (Data->iEdgedWidth/2) * y) * 8;
1759            Data->b_RefP[4] = b_Ref->u + (x + (Data->iEdgedWidth/2) * y) * 8;
1760            Data->b_RefP[5] = b_Ref->v + (x + (Data->iEdgedWidth/2) * y) * 8;
1761    
1762            k = Data->qpel ? 4 : 2;
1763            Data->max_dx = k * (pParam->width - x * 16);
1764            Data->max_dy = k * (pParam->height - y * 16);
1765            Data->min_dx = -k * (16 + x * 16);
1766            Data->min_dy = -k * (16 + y * 16);
1767    
1768            Data->referencemv = Data->qpel ? b_mb->qmvs : b_mb->mvs;
1769            Data->qpel_precision = 0;
1770    
1771            for (k = 0; k < 4; k++) {
1772                    pMB->mvs[k].x = Data->directmvF[k].x = ((TRB * Data->referencemv[k].x) / TRD);
1773                    pMB->b_mvs[k].x = Data->directmvB[k].x = ((TRB - TRD) * Data->referencemv[k].x) / TRD;
1774                    pMB->mvs[k].y = Data->directmvF[k].y = ((TRB * Data->referencemv[k].y) / TRD);
1775                    pMB->b_mvs[k].y = Data->directmvB[k].y = ((TRB - TRD) * Data->referencemv[k].y) / TRD;
1776    
1777                    if ( (pMB->b_mvs[k].x > Data->max_dx) | (pMB->b_mvs[k].x < Data->min_dx)
1778                            | (pMB->b_mvs[k].y > Data->max_dy) | (pMB->b_mvs[k].y < Data->min_dy) ) {
1779    
1780                            *best_sad = 256*4096; // in that case, we won't use direct mode
1781                            pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
1782                            pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;
1783                            return 256*4096;
1784                    }
1785                    if (b_mb->mode != MODE_INTER4V) {
1786                            pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1787                            pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];
1788                            Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1789                            Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1790                            break;
1791                    }
1792          }          }
1793    
1794          if (currMV->x > max_dx)          CheckCandidate = b_mb->mode == MODE_INTER4V ? CheckCandidateDirect : CheckCandidateDirectno4v;
                 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;  
   
 /***************** This is predictor SET A: only median prediction ******************/  
1795    
1796          iMinSAD = sad16( cur,          CheckCandidate(0, 0, 255, &k, Data);
                 get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),  
                 iEdgedWidth, MV_MAX_ERROR);  
         iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;  
1797    
1798  // thresh1 is fixed to 256  // initial (fast) skip decision
1799          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if (*Data->iMinSAD < pMB->quant * INITIAL_SKIP_THRESH * (2 + Data->chroma?1:0)) {
1800                  {                  //possible skip
1801                          if (MotionFlags & PMV_QUICKSTOP16)                  if (Data->chroma) {
1802                                  goto EPZS16_Terminate_without_Refine;                          pMB->mode = MODE_DIRECT_NONE_MV;
1803                          if (MotionFlags & PMV_EARLYSTOP16)                          return *Data->iMinSAD; // skip.
1804                                  goto EPZS16_Terminate_with_Refine;                  } else {
1805                            SkipDecisionB(pCur, f_Ref, b_Ref, pMB, x, y, Data);
1806                            if (pMB->mode == MODE_DIRECT_NONE_MV) return *Data->iMinSAD; // skip.
1807                    }
1808                  }                  }
1809    
1810  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/          *Data->iMinSAD += Data->lambda16;
1811            skip_sad = *Data->iMinSAD;
1812    
1813  // previous frame MV  //      DIRECT MODE DELTA VECTOR SEARCH.
1814          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  //      This has to be made more effective, but at the moment I'm happy it's running at all
1815    
1816  // set threshhold based on Min of Prediction and SAD of collocated block          if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
1817  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1818                            else MainSearchPtr = DiamondSearch;
1819    
1820          if ((x==0) && (y==0) )          MainSearchPtr(0, 0, Data, 255);
         {  
                 thresh2 =  512;  
         }  
         else  
         {  
 /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */  
1821    
1822                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;          SubpelRefine(Data);
         }  
1823    
1824  // MV=(0,0) is often a good choice          *best_sad = *Data->iMinSAD;
1825    
1826          CHECK_MV16_ZERO;          if (Data->qpel || b_mb->mode == MODE_INTER4V) pMB->mode = MODE_DIRECT;
1827            else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1828    
1829            pMB->pmvs[3] = *Data->currentMV;
1830    
1831  // left neighbour, if allowed          for (k = 0; k < 4; k++) {
1832          if (x != 0)                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1833          {                  pMB->b_mvs[k].x = (     (Data->currentMV->x == 0)
1834                  if (!(MotionFlags & PMV_HALFPEL16 ))                                                          ? Data->directmvB[k].x
1835                  {       pmv[1].x = EVEN(pmv[1].x);                                                          :pMB->mvs[k].x - Data->referencemv[k].x);
1836                          pmv[1].y = EVEN(pmv[1].y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1837                  }                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1838                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                                                          ? Data->directmvB[k].y
1839                                                            : pMB->mvs[k].y - Data->referencemv[k].y);
1840                    if (Data->qpel) {
1841                            pMB->qmvs[k].x = pMB->mvs[k].x; pMB->mvs[k].x /= 2;
1842                            pMB->b_qmvs[k].x = pMB->b_mvs[k].x; pMB->b_mvs[k].x /= 2;
1843                            pMB->qmvs[k].y = pMB->mvs[k].y; pMB->mvs[k].y /= 2;
1844                            pMB->b_qmvs[k].y = pMB->b_mvs[k].y; pMB->b_mvs[k].y /= 2;
1845          }          }
1846    
1847  // top neighbour, if allowed                  if (b_mb->mode != MODE_INTER4V) {
1848          if (y != 0)                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1849          {                          pMB->b_mvs[3] = pMB->b_mvs[2] = pMB->b_mvs[1] = pMB->b_mvs[0];
1850                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pMB->qmvs[3] = pMB->qmvs[2] = pMB->qmvs[1] = pMB->qmvs[0];
1851                  {       pmv[2].x = EVEN(pmv[2].x);                          pMB->b_qmvs[3] = pMB->b_qmvs[2] = pMB->b_qmvs[1] = pMB->b_qmvs[0];
1852                          pmv[2].y = EVEN(pmv[2].y);                          break;
1853                    }
1854            }
1855            return skip_sad;
1856                  }                  }
                 CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);  
1857    
1858  // top right neighbour, if allowed  static void
1859                  if ((uint32_t)x != (iWcount-1))  SearchInterpolate(const IMAGE * const f_Ref,
1860                  {                                  const uint8_t * const f_RefH,
1861                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  const uint8_t * const f_RefV,
1862                          {       pmv[3].x = EVEN(pmv[3].x);                                  const uint8_t * const f_RefHV,
1863                                  pmv[3].y = EVEN(pmv[3].y);                                  const IMAGE * const b_Ref,
1864                                    const uint8_t * const b_RefH,
1865                                    const uint8_t * const b_RefV,
1866                                    const uint8_t * const b_RefHV,
1867                                    const IMAGE * const pCur,
1868                                    const int x, const int y,
1869                                    const uint32_t fcode,
1870                                    const uint32_t bcode,
1871                                    const uint32_t MotionFlags,
1872                                    const MBParam * const pParam,
1873                                    const VECTOR * const f_predMV,
1874                                    const VECTOR * const b_predMV,
1875                                    MACROBLOCK * const pMB,
1876                                    int32_t * const best_sad,
1877                                    SearchData * const fData)
1878    
1879    {
1880    
1881            int iDirection, i, j;
1882            SearchData bData;
1883    
1884            fData->qpel_precision = 0;
1885            memcpy(&bData, fData, sizeof(SearchData)); //quick copy of common data
1886            *fData->iMinSAD = 4096*256;
1887            bData.currentMV++; bData.currentQMV++;
1888            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1889    
1890            i = (x + y * fData->iEdgedWidth) * 16;
1891    
1892            bData.b_RefP[0] = fData->RefP[0] = f_Ref->y + i;
1893            bData.b_RefP[2] = fData->RefP[2] = f_RefH + i;
1894            bData.b_RefP[1] = fData->RefP[1] = f_RefV + i;
1895            bData.b_RefP[3] = fData->RefP[3] = f_RefHV + i;
1896            bData.RefP[0] = fData->b_RefP[0] = b_Ref->y + i;
1897            bData.RefP[2] = fData->b_RefP[2] = b_RefH + i;
1898            bData.RefP[1] = fData->b_RefP[1] = b_RefV + i;
1899            bData.RefP[3] = fData->b_RefP[3] = b_RefHV + i;
1900            bData.b_RefP[4] = fData->RefP[4] = f_Ref->u + (x + (fData->iEdgedWidth/2) * y) * 8;
1901            bData.b_RefP[5] = fData->RefP[5] = f_Ref->v + (x + (fData->iEdgedWidth/2) * y) * 8;
1902            bData.RefP[4] = fData->b_RefP[4] = b_Ref->u + (x + (fData->iEdgedWidth/2) * y) * 8;
1903            bData.RefP[5] = fData->b_RefP[5] = b_Ref->v + (x + (fData->iEdgedWidth/2) * y) * 8;
1904    
1905            bData.bpredMV = fData->predMV = *f_predMV;
1906            fData->bpredMV = bData.predMV = *b_predMV;
1907            fData->currentMV[0] = fData->currentMV[2];
1908    
1909            get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode - fData->qpel, 0, 0);
1910            get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode - fData->qpel, 0, 0);
1911    
1912            if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1913            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dx;
1914            if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dy;
1915            if (fData->currentMV[0].y < fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1916    
1917            if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1918            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dx;
1919            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dy;
1920            if (fData->currentMV[1].y < bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1921    
1922            CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
1923    
1924    //diamond
1925            do {
1926                    iDirection = 255;
1927                    // forward MV moves
1928                    i = fData->currentMV[0].x; j = fData->currentMV[0].y;
1929    
1930                    CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1931                    CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1932                    CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1933                    CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
1934    
1935                    // backward MV moves
1936                    i = fData->currentMV[1].x; j = fData->currentMV[1].y;
1937                    fData->currentMV[2] = fData->currentMV[0];
1938                    CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1939                    CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1940                    CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
1941                    CheckCandidateInt(i, j - 1, 0, &iDirection, &bData);
1942    
1943            } while (!(iDirection));
1944    
1945    //qpel refinement
1946            if (fData->qpel) {
1947                    if (*fData->iMinSAD > *best_sad + 500) return;
1948                    CheckCandidate = CheckCandidateInt;
1949                    fData->qpel_precision = bData.qpel_precision = 1;
1950                    get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, 1, 0);
1951                    get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, 1, 0);
1952                    fData->currentQMV[2].x = fData->currentQMV[0].x = 2 * fData->currentMV[0].x;
1953                    fData->currentQMV[2].y = fData->currentQMV[0].y = 2 * fData->currentMV[0].y;
1954                    fData->currentQMV[1].x = 2 * fData->currentMV[1].x;
1955                    fData->currentQMV[1].y = 2 * fData->currentMV[1].y;
1956                    SubpelRefine(fData);
1957                    if (*fData->iMinSAD > *best_sad + 300) return;
1958                    fData->currentQMV[2] = fData->currentQMV[0];
1959                    SubpelRefine(&bData);
1960            }
1961    
1962            *fData->iMinSAD += (2+3) * fData->lambda16; // two bits are needed to code interpolate mode.
1963    
1964            if (*fData->iMinSAD < *best_sad) {
1965                    *best_sad = *fData->iMinSAD;
1966                    pMB->mvs[0] = fData->currentMV[0];
1967                    pMB->b_mvs[0] = fData->currentMV[1];
1968                    pMB->mode = MODE_INTERPOLATE;
1969                    if (fData->qpel) {
1970                            pMB->qmvs[0] = fData->currentQMV[0];
1971                            pMB->b_qmvs[0] = fData->currentQMV[1];
1972                            pMB->pmvs[1].x = pMB->qmvs[0].x - f_predMV->x;
1973                            pMB->pmvs[1].y = pMB->qmvs[0].y - f_predMV->y;
1974                            pMB->pmvs[0].x = pMB->b_qmvs[0].x - b_predMV->x;
1975                            pMB->pmvs[0].y = pMB->b_qmvs[0].y - b_predMV->y;
1976                    } else {
1977                            pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;
1978                            pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;
1979                            pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;
1980                            pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;
1981                          }                          }
                         CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);  
1982                  }                  }
1983          }          }
1984    
1985  /* Terminate if MinSAD <= T_2  void
1986     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]  MotionEstimationBVOP(MBParam * const pParam,
1987  */                                          FRAMEINFO * const frame,
1988                                            const int32_t time_bp,
1989          if ( (iMinSAD <= thresh2)                                          const int32_t time_pp,
1990                  || ( MVequal(*currMV,pMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )                                          // forward (past) reference
1991                                            const MACROBLOCK * const f_mbs,
1992                                            const IMAGE * const f_ref,
1993                                            const IMAGE * const f_refH,
1994                                            const IMAGE * const f_refV,
1995                                            const IMAGE * const f_refHV,
1996                                            // backward (future) reference
1997                                            const FRAMEINFO * const b_reference,
1998                                            const IMAGE * const b_ref,
1999                                            const IMAGE * const b_refH,
2000                                            const IMAGE * const b_refV,
2001                                            const IMAGE * const b_refHV)
2002                  {                  {
2003                          if (MotionFlags & PMV_QUICKSTOP16)          uint32_t i, j;
2004                                  goto EPZS16_Terminate_without_Refine;          int32_t best_sad;
2005                          if (MotionFlags & PMV_EARLYSTOP16)          uint32_t skip_sad;
2006                                  goto EPZS16_Terminate_with_Refine;          int f_count = 0, b_count = 0, i_count = 0, d_count = 0, n_count = 0;
2007                  }          const MACROBLOCK * const b_mbs = b_reference->mbs;
2008    
2009  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
2010    
2011          backupMV = pMB->mvs[0];                 // last MV          const int32_t TRB = time_pp - time_bp;
2012          backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X          const int32_t TRD = time_pp;
2013          backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y  
2014    // some pre-inintialized data for the rest of the search
2015    
2016            SearchData Data;
2017            int32_t iMinSAD;
2018            VECTOR currentMV[3];
2019            VECTOR currentQMV[3];
2020            int32_t temp[8];
2021            memset(&Data, 0, sizeof(SearchData));
2022            Data.iEdgedWidth = pParam->edged_width;
2023            Data.currentMV = currentMV; Data.currentQMV = currentQMV;
2024            Data.iMinSAD = &iMinSAD;
2025            Data.lambda16 = lambda_vec16[frame->quant];
2026            Data.qpel = pParam->m_quarterpel;
2027            Data.rounding = 0;
2028            Data.chroma = frame->motion_flags & PMV_CHROMA8;
2029            Data.temp = temp;
2030    
2031          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);          Data.RefQ = f_refV->u; // a good place, also used in MC (for similar purpose)
2032            // note: i==horizontal, j==vertical
2033            for (j = 0; j < pParam->mb_height; j++) {
2034    
2035  // left neighbour                  f_predMV = b_predMV = zeroMV;   /* prediction is reset at left boundary */
         if (x != 0)  
                 CHECK_MV16_CANDIDATE((oldMB-1)->mvs[0].x,oldMB->mvs[0].y);  
2036    
2037  // top neighbour                  for (i = 0; i < pParam->mb_width; i++) {
2038          if (y != 0)                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;
2039                  CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;
2040    
2041    /* special case, if collocated block is SKIPed in P-VOP: encoding is forward (0,0), cpb=0 without further ado */
2042                            if (b_reference->coding_type != S_VOP)
2043                                    if (b_mb->mode == MODE_NOT_CODED) {
2044                                            pMB->mode = MODE_NOT_CODED;
2045                                            continue;
2046                                    }
2047    
2048  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs                          Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
2049                            Data.CurU = frame->image.u + (j * Data.iEdgedWidth/2 + i) * 8;
2050                            Data.CurV = frame->image.v + (j * Data.iEdgedWidth/2 + i) * 8;
2051                            pMB->quant = frame->quant;
2052    
2053    /* direct search comes first, because it (1) checks for SKIP-mode
2054            and (2) sets very good predictions for forward and backward search */
2055                            skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
2056                                                                            b_ref, b_refH->y, b_refV->y, b_refHV->y,
2057                                                                            &frame->image,
2058                                                                            i, j,
2059                                                                            frame->motion_flags,
2060                                                                            TRB, TRD,
2061                                                                            pParam,
2062                                                                            pMB, b_mb,
2063                                                                            &best_sad,
2064                                                                            &Data);
2065    
2066          if ((uint32_t)x != iWcount-1)                          if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
                 CHECK_MV16_CANDIDATE((pMB+1)->mvs[0].x,oldMB->mvs[0].y);  
2067    
2068  // bottom neighbour, dito                          // forward search
2069          if ((uint32_t)y != iHcount-1)                          SearchBF(f_ref, f_refH->y, f_refV->y, f_refHV->y,
2070                  CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);                                                  &frame->image, i, j,
2071                                                    frame->motion_flags,
2072                                                    frame->fcode, pParam,
2073                                                    pMB, &f_predMV, &best_sad,
2074                                                    MODE_FORWARD, &Data);
2075    
2076  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */                          // backward search
2077          if (iMinSAD <= thresh2)                          SearchBF(b_ref, b_refH->y, b_refV->y, b_refHV->y,
2078                  {                                                  &frame->image, i, j,
2079                          if (MotionFlags & PMV_QUICKSTOP16)                                                  frame->motion_flags,
2080                                  goto EPZS16_Terminate_without_Refine;                                                  frame->bcode, pParam,
2081                          if (MotionFlags & PMV_EARLYSTOP16)                                                  pMB, &b_predMV, &best_sad,
2082                                  goto EPZS16_Terminate_with_Refine;                                                  MODE_BACKWARD, &Data);
2083    
2084                            // interpolate search comes last, because it uses data from forward and backward as prediction
2085                            SearchInterpolate(f_ref, f_refH->y, f_refV->y, f_refHV->y,
2086                                                    b_ref, b_refH->y, b_refV->y, b_refHV->y,
2087                                                    &frame->image,
2088                                                    i, j,
2089                                                    frame->fcode, frame->bcode,
2090                                                    frame->motion_flags,
2091                                                    pParam,
2092                                                    &f_predMV, &b_predMV,
2093                                                    pMB, &best_sad,
2094                                                    &Data);
2095    
2096    // final skip decision
2097                            if ( (skip_sad < frame->quant * MAX_SAD00_FOR_SKIP * 2)
2098                                            && ((100*best_sad)/(skip_sad+1) > FINAL_SKIP_THRESH) )
2099                                    SkipDecisionB(&frame->image, f_ref, b_ref, pMB, i, j, &Data);
2100    
2101                            switch (pMB->mode) {
2102                                    case MODE_FORWARD:
2103                                            f_count++;
2104                                            f_predMV = Data.qpel ? pMB->qmvs[0] : pMB->mvs[0];
2105                                            break;
2106                                    case MODE_BACKWARD:
2107                                            b_count++;
2108                                            b_predMV = Data.qpel ? pMB->b_qmvs[0] : pMB->b_mvs[0];
2109                                            break;
2110                                    case MODE_INTERPOLATE:
2111                                            i_count++;
2112                                            f_predMV = Data.qpel ? pMB->qmvs[0] : pMB->mvs[0];
2113                                            b_predMV = Data.qpel ? pMB->b_qmvs[0] : pMB->b_mvs[0];
2114                                            break;
2115                                    case MODE_DIRECT:
2116                                    case MODE_DIRECT_NO4V:
2117                                            d_count++;
2118                                    default:
2119                                            break;
2120                            }
2121                    }
2122            }
2123                  }                  }
2124    
2125  /************ (if Diamond Search)  **************/  static __inline void
2126    MEanalyzeMB (   const uint8_t * const pRef,
2127                                    const uint8_t * const pCur,
2128                                    const int x,
2129                                    const int y,
2130                                    const MBParam * const pParam,
2131                                    MACROBLOCK * const pMBs,
2132                                    SearchData * const Data)
2133    {
2134    
2135          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          int i, mask;
2136            VECTOR pmv[3];
2137            MACROBLOCK * const pMB = &pMBs[x + y * pParam->mb_width];
2138    
2139  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */          for (i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
2140    
2141          if (MotionFlags & PMV_USESQUARES16)          //median is only used as prediction. it doesn't have to be real
2142                  EPZSMainSearchPtr = Square16_MainSearch;          if (x == 1 && y == 1) Data->predMV.x = Data->predMV.y = 0;
2143          else          else
2144                  EPZSMainSearchPtr = Diamond16_MainSearch;                  if (x == 1) //left macroblock does not have any vector now
2145                            Data->predMV = (pMB - pParam->mb_width)->mvs[0]; // top instead of median
2146                    else if (y == 1) // top macroblock doesn't have it's vector
2147                            Data->predMV = (pMB - 1)->mvs[0]; // left instead of median
2148                            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); //else median
2149    
2150          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2151                          x, y,                                  pParam->width, pParam->height, Data->iFcode - pParam->m_quarterpel, 0, 0);
                         currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,  
                         2, iFcode, iQuant, 0);  
2152    
2153          if (iSAD < iMinSAD)          Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
2154          {          Data->RefP[0] = pRef + (x + y * pParam->edged_width) * 16;
                 *currMV = newMV;  
                 iMinSAD = iSAD;  
         }  
2155    
2156            pmv[1].x = EVEN(pMB->mvs[0].x);
2157            pmv[1].y = EVEN(pMB->mvs[0].y);
2158            pmv[2].x = EVEN(Data->predMV.x);
2159            pmv[2].y = EVEN(Data->predMV.y);
2160            pmv[0].x = pmv[0].y = 0;
2161    
2162          if (MotionFlags & PMV_EXTSEARCH16)          CheckCandidate32I(0, 0, 255, &i, Data);
         {  
 /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  
2163    
2164                  if (!(MVequal(pmv[0],backupMV)) )          if (*Data->iMinSAD > 4 * MAX_SAD00_FOR_SKIP) {
2165                  {  
2166                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                  if (!(mask = make_mask(pmv, 1)))
2167                                  x, y,                          CheckCandidate32I(pmv[1].x, pmv[1].y, mask, &i, Data);
2168                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                  if (!(mask = make_mask(pmv, 2)))
2169                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                          CheckCandidate32I(pmv[2].x, pmv[2].y, mask, &i, Data);
2170    
2171                    if (*Data->iMinSAD > 4 * MAX_SAD00_FOR_SKIP) // diamond only if needed
2172                            DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
2173                  }                  }
2174    
2175                  if (iSAD < iMinSAD)          for (i = 0; i < 4; i++) {
2176                  {                  MACROBLOCK * MB = &pMBs[x + (i&1) + (y+(i>>1)) * pParam->mb_width];
2177                          *currMV = newMV;                  MB->mvs[0] = MB->mvs[1] = MB->mvs[2] = MB->mvs[3] = Data->currentMV[i];
2178                          iMinSAD = iSAD;                  MB->mode = MODE_INTER;
2179                    MB->sad16 = Data->iMinSAD[i+1];
2180            }
2181                  }                  }
2182    
2183                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )  #define INTRA_THRESH    1800
2184                  {  #define INTER_THRESH    1200
                         iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,  
                                 x, y,  
                         0, 0, iMinSAD, &newMV,  
                         pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, /*iDiamondSize*/ 2, iFcode, iQuant, 0);  
2185    
2186                          if (iSAD < iMinSAD)  int
2187                          {  MEanalysis(     const IMAGE * const pRef,
2188                                  *currMV = newMV;                          const FRAMEINFO * const Current,
2189                                  iMinSAD = iSAD;                          const MBParam * const pParam,
2190                          }                          const int maxIntra, //maximum number if non-I frames
2191                            const int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame
2192                            const int bCount,  // number of B frames in a row
2193                            const int b_thresh)
2194    {
2195            uint32_t x, y, intra = 0;
2196            int sSAD = 0;
2197            MACROBLOCK * const pMBs = Current->mbs;
2198            const IMAGE * const pCurrent = &Current->image;
2199            int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH + 10*b_thresh;
2200            int s = 0, blocks = 0;
2201    
2202            int32_t iMinSAD[5], temp[5];
2203            VECTOR currentMV[5];
2204            SearchData Data;
2205            Data.iEdgedWidth = pParam->edged_width;
2206            Data.currentMV = currentMV;
2207            Data.iMinSAD = iMinSAD;
2208            Data.iFcode = Current->fcode;
2209            Data.temp = temp;
2210            CheckCandidate = CheckCandidate32I;
2211    
2212            if (intraCount != 0 && intraCount < 10) // we're right after an I frame
2213                    IntraThresh += 15 * (intraCount - 10) * (intraCount - 10);
2214            else
2215                    if ( 5*(maxIntra - intraCount) < maxIntra) // we're close to maximum. 2 sec when max is 10 sec
2216                            IntraThresh -= (IntraThresh * (maxIntra - 8*(maxIntra - intraCount)))/maxIntra;
2217    
2218            InterThresh -= (350 - 8*b_thresh) * bCount;
2219            if (InterThresh < 300 + 5*b_thresh) InterThresh = 300 + 5*b_thresh;
2220    
2221            if (sadInit) (*sadInit) ();
2222    
2223            for (y = 1; y < pParam->mb_height-1; y += 2) {
2224                    for (x = 1; x < pParam->mb_width-1; x += 2) {
2225                            int i;
2226                            blocks += 4;
2227    
2228                            if (bCount == 0) pMBs[x + y * pParam->mb_width].mvs[0] = zeroMV;
2229                            else { //extrapolation of the vector found for last frame
2230                                    pMBs[x + y * pParam->mb_width].mvs[0].x =
2231                                            (pMBs[x + y * pParam->mb_width].mvs[0].x * (bCount+1) ) / bCount;
2232                                    pMBs[x + y * pParam->mb_width].mvs[0].y =
2233                                            (pMBs[x + y * pParam->mb_width].mvs[0].y * (bCount+1) ) / bCount;
2234                            }
2235    
2236                            MEanalyzeMB(pRef->y, pCurrent->y, x, y, pParam, pMBs, &Data);
2237    
2238                            for (i = 0; i < 4; i++) {
2239                                    int dev;
2240                                    MACROBLOCK *pMB = &pMBs[x+(i&1) + (y+(i>>1)) * pParam->mb_width];
2241                                    if (pMB->sad16 > IntraThresh) {
2242                                            dev = dev16(pCurrent->y + (x + (i&1) + (y + (i>>1)) * pParam->edged_width) * 16,
2243                                                                            pParam->edged_width);
2244                                            if (dev + IntraThresh < pMB->sad16) {
2245                                                    pMB->mode = MODE_INTRA;
2246                                                    if (++intra > ((pParam->mb_height-2)*(pParam->mb_width-2))/2) return I_VOP;
2247                  }                  }
2248          }          }
2249                                    if (pMB->mvs[0].x == 0 && pMB->mvs[0].y == 0) s++;
2250    
2251  /***************        Choose best MV found     **************/                                  sSAD += pMB->sad16;
2252                            }
2253  EPZS16_Terminate_with_Refine:                  }
2254          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          }
                 iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,  
                                 x, y,  
                                 currMV, iMinSAD,  
                                 pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);  
2255    
2256  EPZS16_Terminate_without_Refine:          sSAD /= blocks;
2257            s = (10*s) / blocks;
2258    
2259          *oldMB = *pMB;          if (s > 4) sSAD += (s - 2) * (60 - 2*b_thresh); //static block - looks bad when in bframe...
2260    
2261          currPMV->x = currMV->x - pmv[0].x;          if (sSAD > InterThresh ) return P_VOP;
2262          currPMV->y = currMV->y - pmv[0].y;          emms();
2263          return iMinSAD;          return B_VOP;
2264  }  }
2265    
2266    
2267  int32_t EPZSSearch8(  static WARPPOINTS
2268                                          const uint8_t * const pRef,  GlobalMotionEst(const MACROBLOCK * const pMBs,
                                         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,  
2269                                          const MBParam * const pParam,                                          const MBParam * const pParam,
2270                                          const MACROBLOCK * const pMBs,                                  const FRAMEINFO * const current,
2271                                          const MACROBLOCK * const prevMBs,                                  const FRAMEINFO * const reference,
2272                                          VECTOR * const currMV,                                  const IMAGE * const pRefH,
2273                                          VECTOR * const currPMV)                                  const IMAGE * const pRefV,
2274                                    const IMAGE * const pRefHV      )
2275  {  {
     const uint32_t iWcount = pParam->mb_width;  
         const int32_t iWidth = pParam->width;  
         const int32_t iHeight = pParam->height;  
         const int32_t iEdgedWidth = pParam->edged_width;  
   
         const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;  
2276    
2277          int32_t iDiamondSize=1;          const int deltax=8;             // upper bound for difference between a MV and it's neighbour MVs
2278            const int deltay=8;
2279            const int grad=512;             // lower bound for deviation in MB
2280    
2281          int32_t min_dx;          WARPPOINTS gmc;
         int32_t max_dx;  
         int32_t min_dy;  
         int32_t max_dy;  
2282    
2283          VECTOR newMV;          uint32_t mx, my;
         VECTOR backupMV;  
2284    
2285          VECTOR pmv[4];          int MBh = pParam->mb_height;
2286          int32_t psad[8];          int MBw = pParam->mb_width;
2287    
2288          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          int *MBmask= calloc(MBh*MBw,sizeof(int));
2289            double DtimesF[4] = { 0.,0., 0., 0. };
2290            double sol[4] = { 0., 0., 0., 0. };
2291            double a,b,c,n,denom;
2292            double meanx,meany;
2293            int num,oldnum;
2294    
2295          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;          if (!MBmask) {  fprintf(stderr,"Mem error\n");
2296          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;                                          gmc.duv[0].x= gmc.duv[0].y =
2297                                                    gmc.duv[1].x= gmc.duv[1].y =
2298                                                    gmc.duv[2].x= gmc.duv[2].y = 0;
2299                                            return gmc; }
2300    
2301          int32_t bPredEq;  // filter mask of all blocks
         int32_t iMinSAD,iSAD=9999;  
2302    
2303          MainSearch8FuncPtr EPZSMainSearchPtr;          for (my = 1; my < (uint32_t)MBh-1; my++)
2304            for (mx = 1; mx < (uint32_t)MBw-1; mx++)
2305            {
2306                    const int mbnum = mx + my * MBw;
2307                    const MACROBLOCK *pMB = &pMBs[mbnum];
2308                    const VECTOR mv = pMB->mvs[0];
2309    
2310  /* Get maximum range */                  if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
2311          get_range(&min_dx, &max_dx, &min_dy, &max_dy,                          continue;
                         x, y, 8, iWidth, iHeight, iFcode);  
2312    
2313  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */                  if ( ( (abs(mv.x -   (pMB-1)->mvs[0].x) < deltax) && (abs(mv.y -   (pMB-1)->mvs[0].y) < deltay) )
2314                    &&   ( (abs(mv.x -   (pMB+1)->mvs[0].x) < deltax) && (abs(mv.y -   (pMB+1)->mvs[0].y) < deltay) )
2315                    &&   ( (abs(mv.x - (pMB-MBw)->mvs[0].x) < deltax) && (abs(mv.y - (pMB-MBw)->mvs[0].y) < deltay) )
2316                    &&   ( (abs(mv.x - (pMB+MBw)->mvs[0].x) < deltax) && (abs(mv.y - (pMB+MBw)->mvs[0].y) < deltay) ) )
2317                            MBmask[mbnum]=1;
2318            }
2319    
2320          if (!(MotionFlags & PMV_HALFPEL8 ))          for (my = 1; my < (uint32_t)MBh-1; my++)
2321          { min_dx = EVEN(min_dx);          for (mx = 1; mx < (uint32_t)MBw-1; mx++)
2322            max_dx = EVEN(max_dx);          {
2323            min_dy = EVEN(min_dy);                  const uint8_t *const pCur = current->image.y + 16*my*pParam->edged_width + 16*mx;
           max_dy = EVEN(max_dy);  
         }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */  
2324    
2325          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);                  const int mbnum = mx + my * MBw;
2326                    if (!MBmask[mbnum])
2327                            continue;
2328    
2329                    if (sad16 ( pCur, pCur+1 , pParam->edged_width, 65536) <= (uint32_t)grad )
2330                            MBmask[mbnum] = 0;
2331                    if (sad16 ( pCur, pCur+pParam->edged_width, pParam->edged_width, 65536) <= (uint32_t)grad )
2332                            MBmask[mbnum] = 0;
2333    
2334  /* 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.  
 */  
2335    
2336  // Prepare for main loop          emms();
2337    
2338            do {            /* until convergence */
2339    
2340          if (!(MotionFlags & PMV_HALFPEL8))          a = b = c = n = 0;
2341            DtimesF[0] = DtimesF[1] = DtimesF[2] = DtimesF[3] = 0.;
2342            for (my = 0; my < (uint32_t)MBh; my++)
2343                    for (mx = 0; mx < (uint32_t)MBw; mx++)
2344          {          {
2345                  currMV->x = EVEN(currMV->x);                          const int mbnum = mx + my * MBw;
2346                  currMV->y = EVEN(currMV->y);                          const MACROBLOCK *pMB = &pMBs[mbnum];
2347          }                          const VECTOR mv = pMB->mvs[0];
2348    
2349          if (currMV->x > max_dx)                          if (!MBmask[mbnum])
2350                  currMV->x=max_dx;                                  continue;
2351          if (currMV->x < min_dx)  
2352                  currMV->x=min_dx;                          n++;
2353          if (currMV->y > max_dy)                          a += 16*mx+8;
2354                  currMV->y=max_dy;                          b += 16*my+8;
2355          if (currMV->y < min_dy)                          c += (16*mx+8)*(16*mx+8)+(16*my+8)*(16*my+8);
2356                  currMV->y=min_dy;  
2357                            DtimesF[0] += (double)mv.x;
2358                            DtimesF[1] += (double)mv.x*(16*mx+8) + (double)mv.y*(16*my+8);
2359                            DtimesF[2] += (double)mv.x*(16*my+8) - (double)mv.y*(16*mx+8);
2360                            DtimesF[3] += (double)mv.y;
2361                    }
2362    
2363            denom = a*a+b*b-c*n;
2364    
2365    /* Solve the system:    sol = (D'*E*D)^{-1} D'*E*F   */
2366    /* D'*E*F has been calculated in the same loop as matrix */
2367    
2368            sol[0] = -c*DtimesF[0] + a*DtimesF[1] + b*DtimesF[2];
2369            sol[1] =  a*DtimesF[0] - n*DtimesF[1]                           + b*DtimesF[3];
2370            sol[2] =  b*DtimesF[0]                          - n*DtimesF[2] - a*DtimesF[3];
2371            sol[3] =                                 b*DtimesF[1] - a*DtimesF[2] - c*DtimesF[3];
2372    
2373            sol[0] /= denom;
2374            sol[1] /= denom;
2375            sol[2] /= denom;
2376            sol[3] /= denom;
2377    
2378            meanx = meany = 0.;
2379            oldnum = 0;
2380            for (my = 0; my < (uint32_t)MBh; my++)
2381                    for (mx = 0; mx < (uint32_t)MBw; mx++)
2382                    {
2383                            const int mbnum = mx + my * MBw;
2384                            const MACROBLOCK *pMB = &pMBs[mbnum];
2385                            const VECTOR mv = pMB->mvs[0];
2386    
2387  /***************** This is predictor SET A: only median prediction ******************/                          if (!MBmask[mbnum])
2388                                    continue;
2389    
2390                            oldnum++;
2391                            meanx += fabs(( sol[0] + (16*mx+8)*sol[1] + (16*my+8)*sol[2] ) - mv.x );
2392                            meany += fabs(( sol[3] - (16*mx+8)*sol[2] + (16*my+8)*sol[1] ) - mv.y );
2393                    }
2394    
2395          iMinSAD = sad8( cur,          if (4*meanx > oldnum)   /* better fit than 0.25 is useless */
2396                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  meanx /= oldnum;
2397                  iEdgedWidth);          else
2398          iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                  meanx = 0.25;
2399    
2400            if (4*meany > oldnum)
2401                    meany /= oldnum;
2402            else
2403                    meany = 0.25;
2404    
2405  // thresh1 is fixed to 256  /*      fprintf(stderr,"sol = (%8.5f, %8.5f, %8.5f, %8.5f)\n",sol[0],sol[1],sol[2],sol[3]);
2406          if (iMinSAD < 256/4 )          fprintf(stderr,"meanx = %8.5f  meany = %8.5f   %d\n",meanx,meany, oldnum);
2407    */
2408            num = 0;
2409            for (my = 0; my < (uint32_t)MBh; my++)
2410                    for (mx = 0; mx < (uint32_t)MBw; mx++)
2411                  {                  {
2412                          if (MotionFlags & PMV_QUICKSTOP8)                          const int mbnum = mx + my * MBw;
2413                                  goto EPZS8_Terminate_without_Refine;                          const MACROBLOCK *pMB = &pMBs[mbnum];
2414                          if (MotionFlags & PMV_EARLYSTOP8)                          const VECTOR mv = pMB->mvs[0];
                                 goto EPZS8_Terminate_with_Refine;  
                 }  
2415    
2416  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/                          if (!MBmask[mbnum])
2417                                    continue;
2418    
2419                            if  ( ( fabs(( sol[0] + (16*mx+8)*sol[1] + (16*my+8)*sol[2] ) - mv.x ) > meanx )
2420                                    || ( fabs(( sol[3] - (16*mx+8)*sol[2] + (16*my+8)*sol[1] ) - mv.y ) > meany ) )
2421                                    MBmask[mbnum]=0;
2422                            else
2423                                    num++;
2424                    }
2425    
2426  // previous frame MV          } while ( (oldnum != num) && (num>=4) );
         CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
2427    
2428  // MV=(0,0) is often a good choice          if (num < 4)
2429            {
2430                    gmc.duv[0].x= gmc.duv[0].y= gmc.duv[1].x= gmc.duv[1].y= gmc.duv[2].x= gmc.duv[2].y=0;
2431            } else {
2432    
2433          CHECK_MV8_ZERO;                  gmc.duv[0].x=(int)(sol[0]+0.5);
2434                    gmc.duv[0].y=(int)(sol[3]+0.5);
2435    
2436  /* Terminate if MinSAD <= T_2                  gmc.duv[1].x=(int)(sol[1]*pParam->width+0.5);
2437     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]                  gmc.duv[1].y=(int)(-sol[2]*pParam->width+0.5);
 */  
2438    
2439          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */                  gmc.duv[2].x=0;
2440                  {                  gmc.duv[2].y=0;
                         if (MotionFlags & PMV_QUICKSTOP8)  
                                 goto EPZS8_Terminate_without_Refine;  
                         if (MotionFlags & PMV_EARLYSTOP8)  
                                 goto EPZS8_Terminate_with_Refine;  
2441                  }                  }
2442    //      fprintf(stderr,"wp1 = ( %4d, %4d)  wp2 = ( %4d, %4d) \n", gmc.duv[0].x, gmc.duv[0].y, gmc.duv[1].x, gmc.duv[1].y);
2443    
2444  /************ (if Diamond Search)  **************/          free(MBmask);
2445    
2446          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          return gmc;
2447    }
2448    
2449          if (!(MotionFlags & PMV_HALFPELDIAMOND8))  // functions which perform BITS-based search/bitcount
                 iDiamondSize *= 2;  
2450    
2451  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  static int
2452    CountMBBitsInter(SearchData * const Data,
2453                                    const MACROBLOCK * const pMBs, const int x, const int y,
2454                                    const MBParam * const pParam,
2455                                    const uint32_t MotionFlags)
2456    {
2457            int i, iDirection;
2458            int32_t bsad[5];
2459    
2460  //      if (MotionFlags & PMV_USESQUARES8)          CheckCandidate = CheckCandidateBits16;
 //              EPZSMainSearchPtr = Square8_MainSearch;  
 //      else  
                 EPZSMainSearchPtr = Diamond8_MainSearch;  
2461    
2462          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          if (Data->qpel) {
2463                  x, y,                  for(i = 0; i < 5; i++) {
2464                  currMV->x, currMV->y, iMinSAD, &newMV,                          Data->currentMV[i].x = Data->currentQMV[i].x/2;
2465                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                          Data->currentMV[i].y = Data->currentQMV[i].y/2;
2466                  iDiamondSize, iFcode, iQuant, 00);                  }
2467                    Data->qpel_precision = 1;
2468                    CheckCandidateBits16(Data->currentQMV[0].x, Data->currentQMV[0].y, 255, &iDirection, Data);
2469    
2470                    //checking if this vector is perfect. if it is, we stop.
2471                    if (Data->temp[0] == 0 && Data->temp[1] == 0 && Data->temp[2] == 0 && Data->temp[3] == 0)
2472                            return 0; //quick stop
2473    
2474          if (iSAD < iMinSAD)                  if (MotionFlags & (HALFPELREFINE16_BITS | EXTSEARCH_BITS)) { //we have to prepare for halfpixel-precision search
2475          {                          for(i = 0; i < 5; i++) bsad[i] = Data->iMinSAD[i];
2476                  *currMV = newMV;                          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2477                  iMinSAD = iSAD;                                                  pParam->width, pParam->height, Data->iFcode - Data->qpel, 0, Data->rrv);
2478                            Data->qpel_precision = 0;
2479                            if (Data->currentQMV->x & 1 || Data->currentQMV->y & 1)
2480                                    CheckCandidateBits16(Data->currentMV[0].x, Data->currentMV[0].y, 255, &iDirection, Data);
2481          }          }
2482    
2483          if (MotionFlags & PMV_EXTSEARCH8)          } else { // not qpel
         {  
 /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  
   
                 if (!(MVequal(pmv[0],backupMV)) )  
                 {  
                         iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,  
                                 x, y,  
                         pmv[0].x, pmv[0].y, iMinSAD, &newMV,  
                         pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);  
2484    
2485                          if (iSAD < iMinSAD)                  CheckCandidateBits16(Data->currentMV[0].x, Data->currentMV[0].y, 255, &iDirection, Data);
2486                          {                  //checking if this vector is perfect. if it is, we stop.
2487                                  *currMV = newMV;                  if (Data->temp[0] == 0 && Data->temp[1] == 0 && Data->temp[2] == 0 && Data->temp[3] == 0) {
2488                                  iMinSAD = iSAD;                          return 0; //inter
2489                          }                          }
2490                  }                  }
2491    
2492                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )          if (MotionFlags&EXTSEARCH_BITS) SquareSearch(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
                 {  
                         iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,  
                                 x, y,  
                         0, 0, iMinSAD, &newMV,  
                         pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);  
2493    
2494                          if (iSAD < iMinSAD)          if (MotionFlags&HALFPELREFINE16_BITS) SubpelRefine(Data);
2495                          {  
2496                                  *currMV = newMV;          if (Data->qpel) {
2497                                  iMinSAD = iSAD;                  if (MotionFlags&(EXTSEARCH_BITS | HALFPELREFINE16_BITS)) { // there was halfpel-precision search
2498                            for(i = 0; i < 5; i++) if (bsad[i] > Data->iMinSAD[i]) {
2499                                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // we have found a better match
2500                                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
2501                            }
2502    
2503                            // preparing for qpel-precision search
2504                            Data->qpel_precision = 1;
2505                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2506                                            pParam->width, pParam->height, Data->iFcode, 1, 0);
2507                    }
2508                    if (MotionFlags&QUARTERPELREFINE16_BITS) SubpelRefine(Data);
2509                          }                          }
2510    
2511            if (MotionFlags&CHECKPREDICTION_BITS) { //let's check vector equal to prediction
2512                    VECTOR * v = Data->qpel ? Data->currentQMV : Data->currentMV;
2513                    if (!(Data->predMV.x == v->x && Data->predMV.y == v->y))
2514                            CheckCandidateBits16(Data->predMV.x, Data->predMV.y, 255, &iDirection, Data);
2515                  }                  }
2516            return Data->iMinSAD[0];
2517          }          }
2518    
 /***************        Choose best MV found     **************/  
2519    
2520  EPZS8_Terminate_with_Refine:  static int
2521          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step  CountMBBitsInter4v(const SearchData * const Data,
2522                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                                          MACROBLOCK * const pMB, const MACROBLOCK * const pMBs,
2523                                  x, y,                                          const int x, const int y,
2524                                  currMV, iMinSAD,                                          const MBParam * const pParam, const uint32_t MotionFlags,
2525                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                          const VECTOR * const backup)
2526    {
2527    
2528            int cbp = 0, bits = 0, t = 0, i, iDirection;
2529            SearchData Data2, *Data8 = &Data2;
2530            int sumx = 0, sumy = 0;
2531            int16_t *in = Data->dctSpace, *coeff = Data->dctSpace + 64;
2532    
2533  EPZS8_Terminate_without_Refine:          memcpy(Data8, Data, sizeof(SearchData));
2534            CheckCandidate = CheckCandidateBits8;
2535    
2536          currPMV->x = currMV->x - pmv[0].x;          for (i = 0; i < 4; i++) {
2537          currPMV->y = currMV->y - pmv[0].y;                  Data8->iMinSAD = Data->iMinSAD + i + 1;
2538          return iMinSAD;                  Data8->currentMV = Data->currentMV + i + 1;
2539                    Data8->currentQMV = Data->currentQMV + i + 1;
2540                    Data8->Cur = Data->Cur + 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2541                    Data8->RefP[0] = Data->RefP[0] + 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2542                    Data8->RefP[2] = Data->RefP[2] + 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2543                    Data8->RefP[1] = Data->RefP[1] + 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2544                    Data8->RefP[3] = Data->RefP[3] + 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2545    
2546                    if(Data->qpel) {
2547                            Data8->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, i);
2548                            if (i != 0)     t = d_mv_bits(  Data8->currentQMV->x, Data8->currentQMV->y,
2549                                                                                    Data8->predMV, Data8->iFcode, 0, 0);
2550                    } else {
2551                            Data8->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, i);
2552                            if (i != 0)     t = d_mv_bits(  Data8->currentMV->x, Data8->currentMV->y,
2553                                                                                    Data8->predMV, Data8->iFcode, 0, 0);
2554  }  }
2555    
2556                    get_range(&Data8->min_dx, &Data8->max_dx, &Data8->min_dy, &Data8->max_dy, 2*x + (i&1), 2*y + (i>>1), 8,
2557                                            pParam->width, pParam->height, Data8->iFcode, Data8->qpel, 0);
2558    
2559                    *Data8->iMinSAD += t;
2560    
2561                    Data8->qpel_precision = Data8->qpel;
2562                    // checking the vector which has been found by SAD-based 8x8 search (if it's different than the one found so far)
2563                    {
2564                            VECTOR *v = Data8->qpel ? Data8->currentQMV : Data8->currentMV;
2565                            if (!( (v->x == backup[i+1].x) && (v->y == backup[i+1].y) ))
2566                                    CheckCandidateBits8(backup[i+1].x, backup[i+1].y, 255, &iDirection, Data8);
2567                    }
2568    
2569                    if (Data8->qpel) {
2570                            if (MotionFlags&HALFPELREFINE8_BITS || (MotionFlags&PMV_EXTSEARCH8 && MotionFlags&EXTSEARCH_BITS)) { // halfpixel motion search follows
2571                                    int32_t s = *Data8->iMinSAD;
2572                                    Data8->currentMV->x = Data8->currentQMV->x/2;
2573                                    Data8->currentMV->y = Data8->currentQMV->y/2;
2574                                    Data8->qpel_precision = 0;
2575                                    get_range(&Data8->min_dx, &Data8->max_dx, &Data8->min_dy, &Data8->max_dy, 2*x + (i&1), 2*y + (i>>1), 8,
2576                                                            pParam->width, pParam->height, Data8->iFcode - 1, 0, 0);
2577    
2578                                    if (Data8->currentQMV->x & 1 || Data8->currentQMV->y & 1)
2579                                            CheckCandidateBits8(Data8->currentMV->x, Data8->currentMV->y, 255, &iDirection, Data8);
2580    
2581  /* ***********************************************************                                  if (MotionFlags & PMV_EXTSEARCH8 && MotionFlags & EXTSEARCH_BITS)
2582          bvop motion estimation                                          SquareSearch(Data8->currentMV->x, Data8->currentMV->x, Data8, 255);
 // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)  
 ***************************************************************/  
2583    
2584  /*                                  if (MotionFlags & HALFPELREFINE8_BITS) SubpelRefine(Data8);
 void MotionEstimationBVOP(  
                         MBParam * const pParam,  
                         FRAMEINFO * const frame,  
2585    
2586                          // forward (past) reference                                  if(s > *Data8->iMinSAD) { //we have found a better match
2587                          const MACROBLOCK * const f_mbs,                                          Data8->currentQMV->x = 2*Data8->currentMV->x;
2588                      const IMAGE * const f_ref,                                          Data8->currentQMV->y = 2*Data8->currentMV->y;
2589                          const IMAGE * const f_refH,                                  }
                     const IMAGE * const f_refV,  
                         const IMAGE * const f_refHV,  
                         // backward (future) reference  
                         const MACROBLOCK * const b_mbs,  
                     const IMAGE * const b_ref,  
                         const IMAGE * const b_refH,  
                     const IMAGE * const b_refV,  
                         const IMAGE * const b_refHV)  
 {  
     const uint32_t mb_width = pParam->mb_width;  
     const uint32_t mb_height = pParam->mb_height;  
         const int32_t edged_width = pParam->edged_width;  
   
         int32_t i,j;  
   
         int32_t f_sad16;  
         int32_t b_sad16;  
         int32_t i_sad16;  
         int32_t d_sad16;  
         int32_t best_sad;  
2590    
2591          VECTOR pmv_dontcare;                                  Data8->qpel_precision = 1;
2592                                    get_range(&Data8->min_dx, &Data8->max_dx, &Data8->min_dy, &Data8->max_dy, 2*x + (i&1), 2*y + (i>>1), 8,
2593                                                            pParam->width, pParam->height, Data8->iFcode, 1, 0);
2594    
         // note: i==horizontal, j==vertical  
     for (j = 0; j < mb_height; j++)  
         {  
                 for (i = 0; i < mb_width; i++)  
                 {  
                         MACROBLOCK *mb = &frame->mbs[i + j*mb_width];  
                         const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];  
                         const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];  
   
                         if (b_mb->mode == MODE_INTER  
                                 && b_mb->cbp == 0  
                                 && b_mb->mvs[0].x == 0  
                                 && b_mb->mvs[0].y == 0)  
                         {  
                                 mb->mode = MB_IGNORE;  
                                 mb->mvs[0].x = 0;  
                                 mb->mvs[0].y = 0;  
                                 mb->b_mvs[0].x = 0;  
                                 mb->b_mvs[0].y = 0;  
                                 continue;  
2595                          }                          }
2596                            if (MotionFlags & QUARTERPELREFINE8_BITS) SubpelRefine(Data8);
2597    
2598                    } else // not qpel
2599                            if (MotionFlags & HALFPELREFINE8_BITS) SubpelRefine(Data8); //halfpel mode, halfpel refinement
2600    
2601                          // forward search                  //checking vector equal to predicion
2602                          f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                  if (i != 0 && MotionFlags & CHECKPREDICTION_BITS) {
2603                                                  &frame->image,                          const VECTOR * v = Data->qpel ? Data8->currentQMV : Data8->currentMV;
2604                                                  i, j,                          if (!(Data8->predMV.x == v->x && Data8->predMV.y == v->y))
2605                                                  frame->motion_flags,  frame->quant, frame->fcode,                                  CheckCandidateBits8(Data8->predMV.x, Data8->predMV.y, 255, &iDirection, Data8);
2606                                                  pParam,                  }
                                                 f_mbs,  
                                                 &mb->mvs[0], &pmv_dontcare);    // ignore pmv  
2607    
2608                          // backward search                  bits += *Data8->iMinSAD;
2609                          b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                  if (bits >= Data->iMinSAD[0]) break; // no chances for INTER4V
2610                                                  &frame->image,  
2611                                                  i, j,                  // MB structures for INTER4V mode; we have to set them here, we don't have predictor anywhere else
2612                                                  frame->motion_flags,  frame->quant, frame->bcode,                  if(Data->qpel) {
2613                                                  pParam,                          pMB->pmvs[i].x = Data8->currentQMV->x - Data8->predMV.x;
2614                                                  b_mbs,                          pMB->pmvs[i].y = Data8->currentQMV->y - Data8->predMV.y;
2615                                                  &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv                          pMB->qmvs[i] = *Data8->currentQMV;
2616                            sumx += Data8->currentQMV->x/2;
2617                            sumy += Data8->currentQMV->y/2;
2618                    } else {
2619                            pMB->pmvs[i].x = Data8->currentMV->x - Data8->predMV.x;
2620                            pMB->pmvs[i].y = Data8->currentMV->y - Data8->predMV.y;
2621                            sumx += Data8->currentMV->x;
2622                            sumy += Data8->currentMV->y;
2623                    }
2624                    pMB->mvs[i] = *Data8->currentMV;
2625                    pMB->sad8[i] = 4 * *Data8->iMinSAD;
2626                    if (Data8->temp[0]) cbp |= 1 << (5 - i);
2627            }
2628    
2629                          // interpolate search (simple, but effective)          if (bits < *Data->iMinSAD) { // there is still a chance for inter4v mode. let's check chroma
2630                          i_sad16 = sad16bi_c(                  const uint8_t * ptr;
2631                                          frame->image.y + i*16 + j*16*edged_width,                  sumx = (sumx >> 3) + roundtab_76[sumx & 0xf];
2632                                          get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                  sumy = (sumy >> 3) + roundtab_76[sumy & 0xf];
                                                 i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),  
                                         get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,  
                                                 i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),  
                                         edged_width);  
   
                         // TODO: direct search  
                         // predictor + range of [-32,32]  
                         d_sad16 = 65535;  
2633    
2634                    //chroma U
2635                    ptr = interpolate8x8_switch2(Data->RefQ + 64, Data->RefP[4], 0, 0, sumx, sumy, Data->iEdgedWidth/2, Data->rounding);
2636                    transfer_8to16subro(in, Data->CurU, ptr, Data->iEdgedWidth/2);
2637                    fdct(in);
2638                    if (Data->lambda8 == 0) i = quant_inter(coeff, in, Data->lambda16);
2639                    else i = quant4_inter(coeff, in, Data->lambda16);
2640                    if (i > 0) {
2641                            bits += CodeCoeffInter_CalcBits(coeff, scan_tables[0]);
2642                            cbp |= 1 << (5 - 4);
2643                    }
2644    
2645                          if (f_sad16 < b_sad16)                  if (bits < *Data->iMinSAD) { // still possible
2646                          {                          //chroma V
2647                                  best_sad = f_sad16;                          ptr = interpolate8x8_switch2(Data->RefQ + 64, Data->RefP[5], 0, 0, sumx, sumy, Data->iEdgedWidth/2, Data->rounding);
2648                                  mb->mode = MB_FORWARD;                          transfer_8to16subro(in, Data->CurV, ptr, Data->iEdgedWidth/2);
2649                            fdct(in);
2650                            if (Data->lambda8 == 0) i = quant_inter(coeff, in, Data->lambda16);
2651                            else i = quant4_inter(coeff, in, Data->lambda16);
2652                            if (i > 0) {
2653                                    bits += CodeCoeffInter_CalcBits(coeff, scan_tables[0]);
2654                                    cbp |= 1 << (5 - 5);
2655                            }
2656                            bits += xvid_cbpy_tab[15-(cbp>>2)].len;
2657                            bits += mcbpc_inter_tab[(MODE_INTER4V & 7) | ((cbp & 3) << 3)].len;
2658                          }                          }
                         else  
                         {  
                                 best_sad = b_sad16;  
                                 mb->mode = MB_BACKWARD;  
2659                          }                          }
2660    
2661                          if (i_sad16 < best_sad)          return bits;
                         {  
                                 best_sad = i_sad16;  
                                 mb->mode = MB_INTERPOLATE;  
2662                          }                          }
2663    
2664                          if (d_sad16 < best_sad)  
2665    static int
2666    CountMBBitsIntra(const SearchData * const Data)
2667                          {                          {
2668                                  best_sad = d_sad16;          int bits = 1; //this one is ac/dc prediction flag. always 1.
2669                                  mb->mode = MB_DIRECT;          int cbp = 0, i, t, dc = 1024, b_dc;
2670            const uint32_t iQuant = Data->lambda16;
2671            int16_t *in = Data->dctSpace, * coeff = Data->dctSpace + 64;
2672            uint32_t iDcScaler = get_dc_scaler(iQuant, 1);;
2673    
2674            for(i = 0; i < 4; i++) {
2675                    int s = 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2676                    transfer_8to16copy(in, Data->Cur + s, Data->iEdgedWidth);
2677                    fdct(in);
2678                    b_dc = in[0];
2679                    in[0] -= dc;
2680                    dc = b_dc;
2681                    if (Data->lambda8 == 0) quant_intra(coeff, in, iQuant, iDcScaler);
2682                    else quant4_intra(coeff, in, iQuant, iDcScaler);
2683    
2684                    bits += t = CodeCoeffIntra_CalcBits(coeff, scan_tables[0]) + dcy_tab[coeff[0] + 255].len;;
2685                    Data->temp[i] = t;
2686                    if (t != 0)  cbp |= 1 << (5 - i);
2687                    if (bits >= Data->iMinSAD[0]) break;
2688                          }                          }
2689    
2690            if (bits < Data->iMinSAD[0]) { // INTRA still looks good, let's add chroma
2691                    iDcScaler = get_dc_scaler(iQuant, 0);
2692                    //chroma U
2693                    transfer_8to16copy(in, Data->CurU, Data->iEdgedWidth/2);
2694                    fdct(in);
2695                    in[0] -= 1024;
2696                    if (Data->lambda8 == 0) quant_intra(coeff, in, iQuant, iDcScaler);
2697                    else quant4_intra(coeff, in, iQuant, iDcScaler);
2698    
2699                    bits += t = CodeCoeffIntra_CalcBits(coeff, scan_tables[0]) + dcc_tab[coeff[0] + 255].len;
2700                    if (t != 0) cbp |= 1 << (5 - 4);
2701    
2702                    if (bits < Data->iMinSAD[0]) {
2703                            //chroma V
2704                            transfer_8to16copy(in, Data->CurV, Data->iEdgedWidth/2);
2705                            fdct(in);
2706                            in[0] -= 1024;
2707                            if (Data->lambda8 == 0) quant_intra(coeff, in, iQuant, iDcScaler);
2708                            else quant4_intra(coeff, in, iQuant, iDcScaler);
2709    
2710                            bits += t = CodeCoeffIntra_CalcBits(coeff, scan_tables[0]) + dcc_tab[coeff[0] + 255].len;
2711                            if (t != 0) cbp |= 1 << (5 - 5);
2712    
2713                            bits += xvid_cbpy_tab[cbp>>2].len;
2714                            bits += mcbpc_inter_tab[(MODE_INTRA & 7) | ((cbp & 3) << 3)].len;
2715                  }                  }
2716          }          }
2717            return bits;
2718  }  }
   
 */  

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

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