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

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

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

revision 1.44.2.2, Wed Sep 25 21:27:55 2002 UTC revision 1.58.2.26, Wed Aug 6 09:08:37 2003 UTC
# Line 1  Line 1 
1  /**************************************************************************  /*****************************************************************************
2   *   *
3   *      XVID MPEG-4 VIDEO CODEC   *      XVID MPEG-4 VIDEO CODEC
4   *      motion estimation   *  - Motion Estimation related code  -
5   *   *
6   *      This program is an implementation of a part of one or more MPEG-4   *  Copyright(C) 2002 Christoph Lampert <gruel@web.de>
7   *      Video tools as specified in ISO/IEC 14496-2 standard.  Those intending   *               2002 Michael Militzer <michael@xvid.org>
8   *      to use this software module in hardware or software products are   *               2002-2003 Radoslaw Czyz <xvid@syskin.cjb.net>
  *      advised that its use may infringe existing patents or copyrights, and  
  *      any such use would be at such party's own risk.  The original  
  *      developer of this software module and his/her company, and subsequent  
  *      editors and their companies, will have no liability for use of this  
  *      software or modifications or derivatives thereof.  
9   *   *
10   *      This program is free software; you can redistribute it and/or modify   *      This program is free software; you can redistribute it and/or modify
11   *      it under the terms of the GNU General Public License as published by   *      it under the terms of the GNU General Public License as published by
# Line 24  Line 19 
19   *   *
20   *      You should have received a copy of the GNU General Public License   *      You should have received a copy of the GNU General Public License
21   *      along with this program; if not, write to the Free Software   *      along with this program; if not, write to the Free Software
22   *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
23   *   *
24   *************************************************************************/   * $Id$
25     *
26     ****************************************************************************/
27    
28  #include <assert.h>  #include <assert.h>
29  #include <stdio.h>  #include <stdio.h>
30  #include <stdlib.h>  #include <stdlib.h>
31    #include <string.h>     /* memcpy */
32    #include <math.h>       /* lrint */
33    
34  #include "../encoder.h"  #include "../encoder.h"
35  #include "../utils/mbfunctions.h"  #include "../utils/mbfunctions.h"
36  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
37  #include "../global.h"  #include "../global.h"
38  #include "../utils/timer.h"  #include "../utils/timer.h"
39    #include "../image/interpolate8x8.h"
40  #include "motion_est.h"  #include "motion_est.h"
41  #include "motion.h"  #include "motion.h"
42  #include "sad.h"  #include "sad.h"
43    #include "gmc.h"
44  #include "../utils/emms.h"  #include "../utils/emms.h"
45    #include "../dct/fdct.h"
46    
47    /*****************************************************************************
48     * Modified rounding tables -- declared in motion.h
49     * Original tables see ISO spec tables 7-6 -> 7-9
50     ****************************************************************************/
51    
52    const uint32_t roundtab[16] =
53    {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2 };
54    
55    /* K = 4 */
56    const uint32_t roundtab_76[16] =
57    { 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1 };
58    
59    /* K = 2 */
60    const uint32_t roundtab_78[8] =
61    { 0, 0, 1, 1, 0, 0, 0, 1  };
62    
63    /* K = 1 */
64    const uint32_t roundtab_79[4] =
65    { 0, 1, 0, 0 };
66    
67  #define INITIAL_SKIP_THRESH     (10)  #define INITIAL_SKIP_THRESH     (10)
68  #define FINAL_SKIP_THRESH       (50)  #define FINAL_SKIP_THRESH       (50)
69  #define MAX_SAD00_FOR_SKIP      (20)  #define MAX_SAD00_FOR_SKIP      (20)
70  #define MAX_CHROMA_SAD_FOR_SKIP (22)  #define MAX_CHROMA_SAD_FOR_SKIP (22)
 #define SKIP_THRESH_B (25)  
71    
72  #define CHECK_CANDIDATE(X,Y,D) { \  #define CHECK_CANDIDATE(X,Y,D) { \
73  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }  CheckCandidate((X),(Y), (D), &iDirection, data ); }
74    
 #define iDiamondSize 2  
75    
76  static __inline int  /*****************************************************************************
77  d_mv_bits(int x, int y, const uint32_t iFcode)   * Code
78     ****************************************************************************/
79    
80    static __inline uint32_t
81    d_mv_bits(int x, int y, const VECTOR pred, const uint32_t iFcode, const int qpel, const int rrv)
82  {  {
83          int xb, yb;          int bits;
84            const int q = (1 << (iFcode - 1)) - 1;
85    
86          if (x == 0) xb = 1;          x <<= qpel;
87          else {          y <<= qpel;
88                  if (x < 0) x = -x;          if (rrv) { x = RRV_MV_SCALEDOWN(x); y = RRV_MV_SCALEDOWN(y); }
89                  x += (1 << (iFcode - 1)) - 1;  
90            x -= pred.x;
91            bits = (x != 0 ? iFcode:0);
92            x = abs(x);
93            x += q;
94                  x >>= (iFcode - 1);                  x >>= (iFcode - 1);
95                  if (x > 32) x = 32;          bits += mvtab[x];
                 xb = mvtab[x] + iFcode;  
         }  
96    
97          if (y == 0) yb = 1;          y -= pred.y;
98          else {          bits += (y != 0 ? iFcode:0);
99                  if (y < 0) y = -y;          y = abs(y);
100                  y += (1 << (iFcode - 1)) - 1;          y += q;
101                  y >>= (iFcode - 1);                  y >>= (iFcode - 1);
102                  if (y > 32) y = 32;          bits += mvtab[y];
103                  yb = mvtab[y] + iFcode;  
104            return bits;
105    }
106    
107    static int32_t ChromaSAD2(const int fx, const int fy, const int bx, const int by,
108                                                            const SearchData * const data)
109    {
110            int sad;
111            const uint32_t stride = data->iEdgedWidth/2;
112            uint8_t * f_refu = data->RefQ,
113                    * f_refv = data->RefQ + 8,
114                    * b_refu = data->RefQ + 16,
115                    * b_refv = data->RefQ + 24;
116            int offset = (fx>>1) + (fy>>1)*stride;
117    
118            switch (((fx & 1) << 1) | (fy & 1))     {
119                    case 0:
120                            f_refu = (uint8_t*)data->RefP[4] + offset;
121                            f_refv = (uint8_t*)data->RefP[5] + offset;
122                            break;
123                    case 1:
124                            interpolate8x8_halfpel_v(f_refu, data->RefP[4] + offset, stride, data->rounding);
125                            interpolate8x8_halfpel_v(f_refv, data->RefP[5] + offset, stride, data->rounding);
126                            break;
127                    case 2:
128                            interpolate8x8_halfpel_h(f_refu, data->RefP[4] + offset, stride, data->rounding);
129                            interpolate8x8_halfpel_h(f_refv, data->RefP[5] + offset, stride, data->rounding);
130                            break;
131                    default:
132                            interpolate8x8_halfpel_hv(f_refu, data->RefP[4] + offset, stride, data->rounding);
133                            interpolate8x8_halfpel_hv(f_refv, data->RefP[5] + offset, stride, data->rounding);
134                            break;
135            }
136    
137            offset = (bx>>1) + (by>>1)*stride;
138            switch (((bx & 1) << 1) | (by & 1))     {
139                    case 0:
140                            b_refu = (uint8_t*)data->b_RefP[4] + offset;
141                            b_refv = (uint8_t*)data->b_RefP[5] + offset;
142                            break;
143                    case 1:
144                            interpolate8x8_halfpel_v(b_refu, data->b_RefP[4] + offset, stride, data->rounding);
145                            interpolate8x8_halfpel_v(b_refv, data->b_RefP[5] + offset, stride, data->rounding);
146                            break;
147                    case 2:
148                            interpolate8x8_halfpel_h(b_refu, data->b_RefP[4] + offset, stride, data->rounding);
149                            interpolate8x8_halfpel_h(b_refv, data->b_RefP[5] + offset, stride, data->rounding);
150                            break;
151                    default:
152                            interpolate8x8_halfpel_hv(b_refu, data->b_RefP[4] + offset, stride, data->rounding);
153                            interpolate8x8_halfpel_hv(b_refv, data->b_RefP[5] + offset, stride, data->rounding);
154                            break;
155            }
156    
157            sad = sad8bi(data->CurU, b_refu, f_refu, stride);
158            sad += sad8bi(data->CurV, b_refv, f_refv, stride);
159    
160            return sad;
161    }
162    
163    static int32_t
164    ChromaSAD(const int dx, const int dy, const SearchData * const data)
165    {
166            int sad;
167            const uint32_t stride = data->iEdgedWidth/2;
168            int offset = (dx>>1) + (dy>>1)*stride;
169    
170            if (dx == data->temp[5] && dy == data->temp[6]) return data->temp[7]; /* it has been checked recently */
171            data->temp[5] = dx; data->temp[6] = dy; /* backup */
172    
173            switch (((dx & 1) << 1) | (dy & 1))     {
174                    case 0:
175                            sad = sad8(data->CurU, data->RefP[4] + offset, stride);
176                            sad += sad8(data->CurV, data->RefP[5] + offset, stride);
177                            break;
178                    case 1:
179                            sad = sad8bi(data->CurU, data->RefP[4] + offset, data->RefP[4] + offset + stride, stride);
180                            sad += sad8bi(data->CurV, data->RefP[5] + offset, data->RefP[5] + offset + stride, stride);
181                            break;
182                    case 2:
183                            sad = sad8bi(data->CurU, data->RefP[4] + offset, data->RefP[4] + offset + 1, stride);
184                            sad += sad8bi(data->CurV, data->RefP[5] + offset, data->RefP[5] + offset + 1, stride);
185                            break;
186                    default:
187                            interpolate8x8_halfpel_hv(data->RefQ, data->RefP[4] + offset, stride, data->rounding);
188                            sad = sad8(data->CurU, data->RefQ, stride);
189    
190                            interpolate8x8_halfpel_hv(data->RefQ, data->RefP[5] + offset, stride, data->rounding);
191                            sad += sad8(data->CurV, data->RefQ, stride);
192                            break;
193            }
194            data->temp[7] = sad; /* backup, part 2 */
195            return sad;
196    }
197    
198    static __inline const uint8_t *
199    GetReferenceB(const int x, const int y, const uint32_t dir, const SearchData * const data)
200    {
201            /* dir : 0 = forward, 1 = backward */
202            const uint8_t *const *const direction = ( dir == 0 ? data->RefP : data->b_RefP );
203            const int picture = ((x&1)<<1) | (y&1);
204            const int offset = (x>>1) + (y>>1)*data->iEdgedWidth;
205            return direction[picture] + offset;
206    }
207    
208    /* this is a simpler copy of GetReferenceB, but as it's __inline anyway, we can keep the two separate */
209    static __inline const uint8_t *
210    GetReference(const int x, const int y, const SearchData * const data)
211    {
212            const int picture = ((x&1)<<1) | (y&1);
213            const int offset = (x>>1) + (y>>1)*data->iEdgedWidth;
214            return data->RefP[picture] + offset;
215    }
216    
217    static uint8_t *
218    Interpolate8x8qpel(const int x, const int y, const uint32_t block, const uint32_t dir, const SearchData * const data)
219    {
220            /* create or find a qpel-precision reference picture; return pointer to it */
221            uint8_t * Reference = data->RefQ + 16*dir;
222            const uint32_t iEdgedWidth = data->iEdgedWidth;
223            const uint32_t rounding = data->rounding;
224            const int halfpel_x = x/2;
225            const int halfpel_y = y/2;
226            const uint8_t *ref1, *ref2, *ref3, *ref4;
227    
228            ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
229            ref1 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
230            switch( ((x&1)<<1) + (y&1) ) {
231            case 3: /* x and y in qpel resolution - the "corners" (top left/right and */
232                            /* bottom left/right) during qpel refinement */
233                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
234                    ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
235                    ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
236                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
237                    ref3 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
238                    ref4 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
239                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
240                    break;
241    
242            case 1: /* x halfpel, y qpel - top or bottom during qpel refinement */
243                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
244                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
245                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
246                    break;
247    
248            case 2: /* x qpel, y halfpel - left or right during qpel refinement */
249                    ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
250                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
251                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
252                    break;
253    
254            default: /* pure halfpel position */
255                    return (uint8_t *) ref1;
256    
257          }          }
258          return xb + yb;          return Reference;
259  }  }
260    
261    static uint8_t *
262    Interpolate16x16qpel(const int x, const int y, const uint32_t dir, const SearchData * const data)
263    {
264            /* create or find a qpel-precision reference picture; return pointer to it */
265            uint8_t * Reference = data->RefQ + 16*dir;
266            const uint32_t iEdgedWidth = data->iEdgedWidth;
267            const uint32_t rounding = data->rounding;
268            const int halfpel_x = x/2;
269            const int halfpel_y = y/2;
270            const uint8_t *ref1, *ref2, *ref3, *ref4;
271    
272            ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
273            switch( ((x&1)<<1) + (y&1) ) {
274            case 3:
275                    /*
276                     * x and y in qpel resolution - the "corners" (top left/right and
277                     * bottom left/right) during qpel refinement
278                     */
279                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
280                    ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
281                    ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
282                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
283                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
284                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
285                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
286                    break;
287    
288            case 1: /* x halfpel, y qpel - top or bottom during qpel refinement */
289                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
290                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
291                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
292                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
293                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
294                    break;
295    
296            case 2: /* x qpel, y halfpel - left or right during qpel refinement */
297                    ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
298                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
299                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
300                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
301                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
302                    break;
303    
304            default: /* pure halfpel position */
305                    return (uint8_t *) ref1;
306            }
307            return Reference;
308    }
309    
310  /* CHECK_CANDIATE FUNCTIONS START */  /* CHECK_CANDIATE FUNCTIONS START */
311    
312  static void  static void
313  CheckCandidate16(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidate16(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
314  {  {
315          int32_t * const sad = data->temp;          int xc, yc;
         int t;  
316          const uint8_t * Reference;          const uint8_t * Reference;
317            VECTOR * current;
318            int32_t sad; uint32_t t;
319    
320          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
321                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
322    
323          switch ( ((x&1)<<1) + (y&1) ) {          if (!data->qpel_precision) {
324                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;                  Reference = GetReference(x, y, data);
325                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  current = data->currentMV;
326                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;                  xc = x; yc = y;
327                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;          } else { /* x and y are in 1/4 precision */
328                    Reference = Interpolate16x16qpel(x, y, 0, data);
329                    xc = x/2; yc = y/2; /* for chroma sad */
330                    current = data->currentQMV;
331            }
332    
333            sad = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
334            t = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
335    
336            sad += (data->lambda16 * t * sad)>>10;
337            data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))>>10;
338    
339            if (data->chroma && sad < data->iMinSAD[0])
340                    sad += ChromaSAD((xc >> 1) + roundtab_79[xc & 0x3],
341                                                            (yc >> 1) + roundtab_79[yc & 0x3], data);
342    
343            if (sad < data->iMinSAD[0]) {
344                    data->iMinSAD[0] = sad;
345                    current[0].x = x; current[0].y = y;
346                    *dir = Direction;
347            }
348    
349            if (data->temp[1] < data->iMinSAD[1]) {
350                    data->iMinSAD[1] = data->temp[1]; current[1].x = x; current[1].y = y; }
351            if (data->temp[2] < data->iMinSAD[2]) {
352                    data->iMinSAD[2] = data->temp[2]; current[2].x = x; current[2].y = y; }
353            if (data->temp[3] < data->iMinSAD[3]) {
354                    data->iMinSAD[3] = data->temp[3]; current[3].x = x; current[3].y = y; }
355            if (data->temp[4] < data->iMinSAD[4]) {
356                    data->iMinSAD[4] = data->temp[4]; current[4].x = x; current[4].y = y; }
357    }
358    
359    static void
360    CheckCandidate8(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
361    {
362            int32_t sad; uint32_t t;
363            const uint8_t * Reference;
364            VECTOR * current;
365    
366            if ( (x > data->max_dx) || (x < data->min_dx)
367                    || (y > data->max_dy) || (y < data->min_dy) ) return;
368    
369            if (!data->qpel_precision) {
370                    Reference = GetReference(x, y, data);
371                    current = data->currentMV;
372            } else { /* x and y are in 1/4 precision */
373                    Reference = Interpolate8x8qpel(x, y, 0, 0, data);
374                    current = data->currentQMV;
375            }
376    
377            sad = sad8(data->Cur, Reference, data->iEdgedWidth);
378            t = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
379    
380            sad += (data->lambda8 * t * (sad+NEIGH_8X8_BIAS))>>10;
381    
382            if (sad < *(data->iMinSAD)) {
383                    *(data->iMinSAD) = sad;
384                    current->x = x; current->y = y;
385                    *dir = Direction;
386            }
387          }          }
388    
389          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, sad+1);  static void
390    CheckCandidate32(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
391    {
392            uint32_t t;
393            const uint8_t * Reference;
394    
395            if ( (!(x&1) && x !=0) || (!(y&1) && y !=0) || /* non-zero even value */
396                    (x > data->max_dx) || (x < data->min_dx)
397                    || (y > data->max_dy) || (y < data->min_dy) ) return;
398    
399            Reference = GetReference(x, y, data);
400            t = d_mv_bits(x, y, data->predMV, data->iFcode, 0, 1);
401    
402          t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          data->temp[0] = sad32v_c(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
403          data->temp[0] += lambda_vec16[data->iQuant] * t;  
404          data->temp[1] += lambda_vec8[data->iQuant] * t;          data->temp[0] += (data->lambda16 * t * data->temp[0]) >> 10;
405            data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))>>10;
406    
407          if (data->temp[0] < data->iMinSAD[0]) {          if (data->temp[0] < data->iMinSAD[0]) {
408                  data->iMinSAD[0] = data->temp[0];                  data->iMinSAD[0] = data->temp[0];
# Line 117  Line 417 
417                  data->iMinSAD[3] = data->temp[3]; data->currentMV[3].x = x; data->currentMV[3].y = y; }                  data->iMinSAD[3] = data->temp[3]; data->currentMV[3].x = x; data->currentMV[3].y = y; }
418          if (data->temp[4] < data->iMinSAD[4]) {          if (data->temp[4] < data->iMinSAD[4]) {
419                  data->iMinSAD[4] = data->temp[4]; data->currentMV[4].x = x; data->currentMV[4].y = y; }                  data->iMinSAD[4] = data->temp[4]; data->currentMV[4].x = x; data->currentMV[4].y = y; }
   
420  }  }
421    
422  static void  static void
423  CheckCandidate16no4v(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidate16no4v(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
424  {  {
425          int32_t sad;          int32_t sad, xc, yc;
426          const uint8_t * Reference;          const uint8_t * Reference;
427            uint32_t t;
428            VECTOR * current;
429    
430          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
431                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
432    
433          switch ( ((x&1)<<1) + (y&1) )          if (data->rrv && (!(x&1) && x !=0) | (!(y&1) && y !=0) ) return; /* non-zero even value */
         {  
                 case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;  
                 case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;  
                 case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;  
                 default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;  
         }  
434    
435          sad = lambda_vec16[data->iQuant] *          if (data->qpel_precision) { /* x and y are in 1/4 precision */
436                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);                  Reference = Interpolate16x16qpel(x, y, 0, data);
437          sad += sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);                  current = data->currentQMV;
438                    xc = x/2; yc = y/2;
439            } else {
440                    Reference = GetReference(x, y, data);
441                    current = data->currentMV;
442                    xc = x; yc = y;
443            }
444            t = d_mv_bits(x, y, data->predMV, data->iFcode,
445                                            data->qpel^data->qpel_precision, data->rrv);
446    
447            sad = sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);
448            sad += (data->lambda16 * t * sad)>>10;
449    
450            if (data->chroma && sad < *data->iMinSAD)
451                    sad += ChromaSAD((xc >> 1) + roundtab_79[xc & 0x3],
452                                                            (yc >> 1) + roundtab_79[yc & 0x3], data);
453    
454          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
455                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
456                  data->currentMV[0].x = x; data->currentMV[0].y = y;                  current->x = x; current->y = y;
457                  *dir = Direction; }                  *dir = Direction;
458            }
459  }  }
460    
461  static void  static void
462  CheckCandidate16no4vI(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidate16I(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
463  {  {
464          int32_t sad;          int sad;
465    //      int xc, yc;
466            const uint8_t * Reference;
467    //      VECTOR * current;
468    
469          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
470                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
471    
472          sad = lambda_vec16[data->iQuant] *          Reference = GetReference(x, y, data);
473                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);  //      xc = x; yc = y;
474    
475          sad += sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),          sad = sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);
476                                          data->iEdgedWidth, 256*4096);  //      sad += d_mv_bits(x, y, data->predMV, data->iFcode, 0, 0);
477    
478          if (sad < *(data->iMinSAD)) {  /*      if (data->chroma) sad += ChromaSAD((xc >> 1) + roundtab_79[xc & 0x3],
479                  *(data->iMinSAD) = sad;                                                                                  (yc >> 1) + roundtab_79[yc & 0x3], data);
480    */
481    
482            if (sad < data->iMinSAD[0]) {
483                    data->iMinSAD[0] = sad;
484                  data->currentMV[0].x = x; data->currentMV[0].y = y;                  data->currentMV[0].x = x; data->currentMV[0].y = y;
485                  *dir = Direction; }                  *dir = Direction;
486            }
487  }  }
   
488    
489  static void  static void
490  CheckCandidateInt(const int xf, const int yf, const int Direction, int * const dir, const SearchData * const data)  CheckCandidate32I(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
491  {  {
492            /* maximum speed - for P/B/I decision */
493          int32_t sad;          int32_t sad;
         const int xb = data->currentMV[1].x;  
         const int yb = data->currentMV[1].y;  
         const uint8_t *ReferenceF, *ReferenceB;  
494    
495          if (( xf > data->max_dx) || ( xf < data->min_dx)          if ( (x > data->max_dx) || (x < data->min_dx)
496                  || ( yf > data->max_dy) || (yf < data->min_dy)) return;                  || (y > data->max_dy) || (y < data->min_dy) ) return;
497    
498            sad = sad32v_c(data->Cur, data->RefP[0] + (x>>1) + (y>>1)*((int)data->iEdgedWidth),
499                                            data->iEdgedWidth, data->temp+1);
500    
501          switch ( ((xf&1)<<1) + (yf&1) ) {          if (sad < *(data->iMinSAD)) {
502                  case 0 : ReferenceF = data->Ref + xf/2 + (yf/2)*(data->iEdgedWidth); break;                  *(data->iMinSAD) = sad;
503                  case 1 : ReferenceF = data->RefV + xf/2 + ((yf-1)/2)*(data->iEdgedWidth); break;                  data->currentMV[0].x = x; data->currentMV[0].y = y;
504                  case 2 : ReferenceF = data->RefH + (xf-1)/2 + (yf/2)*(data->iEdgedWidth); break;                  *dir = Direction;
                 default : ReferenceF = data->RefHV + (xf-1)/2 + ((yf-1)/2)*(data->iEdgedWidth); break;  
505          }          }
506            if (data->temp[1] < data->iMinSAD[1]) {
507                    data->iMinSAD[1] = data->temp[1]; data->currentMV[1].x = x; data->currentMV[1].y = y; }
508            if (data->temp[2] < data->iMinSAD[2]) {
509                    data->iMinSAD[2] = data->temp[2]; data->currentMV[2].x = x; data->currentMV[2].y = y; }
510            if (data->temp[3] < data->iMinSAD[3]) {
511                    data->iMinSAD[3] = data->temp[3]; data->currentMV[3].x = x; data->currentMV[3].y = y; }
512            if (data->temp[4] < data->iMinSAD[4]) {
513                    data->iMinSAD[4] = data->temp[4]; data->currentMV[4].x = x; data->currentMV[4].y = y; }
514    
         switch ( ((xb&1)<<1) + (yb&1) ) {  
                 case 0 : ReferenceB = data->bRef + xb/2 + (yb/2)*(data->iEdgedWidth); break;  
                 case 1 : ReferenceB = data->bRefV + xb/2 + ((yb-1)/2)*(data->iEdgedWidth); break;  
                 case 2 : ReferenceB = data->bRefH + (xb-1)/2 + (yb/2)*(data->iEdgedWidth); break;  
                 default : ReferenceB = data->bRefHV + (xb-1)/2 + ((yb-1)/2)*(data->iEdgedWidth); break;  
515          }          }
516    
517          sad = lambda_vec16[data->iQuant] *  static void
518                          ( d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode) +  CheckCandidateInt(const int xf, const int yf, const int Direction, int * const dir, const SearchData * const data)
519                            d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode) );  {
520            int32_t sad, xb, yb, xcf, ycf, xcb, ycb;
521            uint32_t t;
522            const uint8_t *ReferenceF, *ReferenceB;
523            VECTOR *current;
524    
525          sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);          if ((xf > data->max_dx) || (xf < data->min_dx) ||
526                    (yf > data->max_dy) || (yf < data->min_dy))
527                    return;
528    
529            if (!data->qpel_precision) {
530                    ReferenceF = GetReference(xf, yf, data);
531                    xb = data->currentMV[1].x; yb = data->currentMV[1].y;
532                    ReferenceB = GetReferenceB(xb, yb, 1, data);
533                    current = data->currentMV;
534                    xcf = xf; ycf = yf;
535                    xcb = xb; ycb = yb;
536            } else {
537                    ReferenceF = Interpolate16x16qpel(xf, yf, 0, data);
538                    xb = data->currentQMV[1].x; yb = data->currentQMV[1].y;
539                    current = data->currentQMV;
540                    ReferenceB = Interpolate16x16qpel(xb, yb, 1, data);
541                    xcf = xf/2; ycf = yf/2;
542                    xcb = xb/2; ycb = yb/2;
543            }
544    
545            t = d_mv_bits(xf, yf, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0)
546                     + d_mv_bits(xb, yb, data->bpredMV, data->iFcode, data->qpel^data->qpel_precision, 0);
547    
548            sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
549            sad += (data->lambda16 * t * sad)>>10;
550    
551            if (data->chroma && sad < *data->iMinSAD)
552                    sad += ChromaSAD2((xcf >> 1) + roundtab_79[xcf & 0x3],
553                                                            (ycf >> 1) + roundtab_79[ycf & 0x3],
554                                                            (xcb >> 1) + roundtab_79[xcb & 0x3],
555                                                            (ycb >> 1) + roundtab_79[ycb & 0x3], data);
556    
557          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
558                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
559                  data->currentMV->x = xf; data->currentMV->y = yf;                  current->x = xf; current->y = yf;
560                  *dir = Direction; }                  *dir = Direction;
561            }
562  }  }
563    
564  static void  static void
565  CheckCandidateDirect(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidateDirect(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
566  {  {
567          int32_t sad;          int32_t sad = 0, xcf = 0, ycf = 0, xcb = 0, ycb = 0;
568          int k;          uint32_t k;
569          const uint8_t *ReferenceF;          const uint8_t *ReferenceF;
570          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
571          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
572    
573          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
574    
         sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);  
   
575          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
576                  mvs.x = data->directmvF[k].x + x;                  mvs.x = data->directmvF[k].x + x;
577                  b_mvs.x = ((x == 0) ?                  b_mvs.x = ((x == 0) ?
# Line 229  Line 583 
583                          data->directmvB[k].y                          data->directmvB[k].y
584                          : mvs.y - data->referencemv[k].y);                          : mvs.y - data->referencemv[k].y);
585    
586                  if (( mvs.x > data->max_dx ) || ( mvs.x < data->min_dx )                  if ((mvs.x > data->max_dx)   || (mvs.x < data->min_dx)   ||
587                          || ( mvs.y > data->max_dy ) || ( mvs.y < data->min_dy )                          (mvs.y > data->max_dy)   || (mvs.y < data->min_dy)   ||
588                          || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )                          (b_mvs.x > data->max_dx) || (b_mvs.x < data->min_dx) ||
589                          || ( b_mvs.y > data->max_dy ) || ( b_mvs.y < data->min_dy )) return;                          (b_mvs.y > data->max_dy) || (b_mvs.y < data->min_dy) )
590                            return;
591                  switch ( ((mvs.x&1)<<1) + (mvs.y&1) ) {  
592                          case 0 : ReferenceF = data->Ref + mvs.x/2 + (mvs.y/2)*(data->iEdgedWidth); break;                  if (data->qpel) {
593                          case 1 : ReferenceF = data->RefV + mvs.x/2 + ((mvs.y-1)/2)*(data->iEdgedWidth); break;                          xcf += mvs.x/2; ycf += mvs.y/2;
594                          case 2 : ReferenceF = data->RefH + (mvs.x-1)/2 + (mvs.y/2)*(data->iEdgedWidth); break;                          xcb += b_mvs.x/2; ycb += b_mvs.y/2;
595                          default : ReferenceF = data->RefHV + (mvs.x-1)/2 + ((mvs.y-1)/2)*(data->iEdgedWidth); break;                  } else {
596                            xcf += mvs.x; ycf += mvs.y;
597                            xcb += b_mvs.x; ycb += b_mvs.y;
598                            mvs.x *= 2; mvs.y *= 2; /* we move to qpel precision anyway */
599                            b_mvs.x *= 2; b_mvs.y *= 2;
600                  }                  }
601    
602                  switch ( ((b_mvs.x&1)<<1) + (b_mvs.y&1) ) {                  ReferenceF = Interpolate8x8qpel(mvs.x, mvs.y, k, 0, data);
603                          case 0 : ReferenceB = data->bRef + b_mvs.x/2 + (b_mvs.y/2)*(data->iEdgedWidth); break;                  ReferenceB = Interpolate8x8qpel(b_mvs.x, b_mvs.y, k, 1, data);
                         case 1 : ReferenceB = data->bRefV + b_mvs.x/2 + ((b_mvs.y-1)/2)*(data->iEdgedWidth); break;  
                         case 2 : ReferenceB = data->bRefH + (b_mvs.x-1)/2 + (b_mvs.y/2)*(data->iEdgedWidth); break;  
                         default : ReferenceB = data->bRefHV + (b_mvs.x-1)/2 + ((b_mvs.y-1)/2)*(data->iEdgedWidth); break;  
                 }  
604    
605                  sad += sad8bi(data->Cur + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),                  sad += sad8bi(data->Cur + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
606                                                  ReferenceF + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),                                                  ReferenceF, ReferenceB, data->iEdgedWidth);
                                                 ReferenceB + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),  
                                                 data->iEdgedWidth);  
607                  if (sad > *(data->iMinSAD)) return;                  if (sad > *(data->iMinSAD)) return;
608          }          }
609    
610            sad += (data->lambda16 * d_mv_bits(x, y, zeroMV, 1, 0, 0) * sad)>>10;
611    
612            if (data->chroma && sad < *data->iMinSAD)
613                    sad += ChromaSAD2((xcf >> 3) + roundtab_76[xcf & 0xf],
614                                                            (ycf >> 3) + roundtab_76[ycf & 0xf],
615                                                            (xcb >> 3) + roundtab_76[xcb & 0xf],
616                                                            (ycb >> 3) + roundtab_76[ycb & 0xf], data);
617    
618          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
619                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
620                  data->currentMV->x = x; data->currentMV->y = y;                  data->currentMV->x = x; data->currentMV->y = y;
621                  *dir = Direction; }                  *dir = Direction;
622            }
623  }  }
624    
625  static void  static void
626  CheckCandidateDirectno4v(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidateDirectno4v(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
627  {  {
628          int32_t sad;          int32_t sad, xcf, ycf, xcb, ycb;
629          const uint8_t *ReferenceF;          const uint8_t *ReferenceF;
630          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
631          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
632    
633          if (( x > 31) || ( x < -31) || ( y > 31) || (y < -31)) return;          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
   
                 sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);  
634    
635          mvs.x = data->directmvF[0].x + x;          mvs.x = data->directmvF[0].x + x;
636          b_mvs.x = ((x == 0) ?          b_mvs.x = ((x == 0) ?
# Line 288  Line 647 
647                  || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )                  || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )
648                  || ( b_mvs.y > data->max_dy ) || ( b_mvs.y < data->min_dy )) return;                  || ( b_mvs.y > data->max_dy ) || ( b_mvs.y < data->min_dy )) return;
649    
650          switch ( ((mvs.x&1)<<1) + (mvs.y&1) ) {          if (data->qpel) {
651                  case 0 : ReferenceF = data->Ref + mvs.x/2 + (mvs.y/2)*(data->iEdgedWidth); break;                  xcf = 4*(mvs.x/2); ycf = 4*(mvs.y/2);
652                  case 1 : ReferenceF = data->RefV + mvs.x/2 + ((mvs.y-1)/2)*(data->iEdgedWidth); break;                  xcb = 4*(b_mvs.x/2); ycb = 4*(b_mvs.y/2);
653                  case 2 : ReferenceF = data->RefH + (mvs.x-1)/2 + (mvs.y/2)*(data->iEdgedWidth); break;                  ReferenceF = Interpolate16x16qpel(mvs.x, mvs.y, 0, data);
654                  default : ReferenceF = data->RefHV + (mvs.x-1)/2 + ((mvs.y-1)/2)*(data->iEdgedWidth); break;                  ReferenceB = Interpolate16x16qpel(b_mvs.x, b_mvs.y, 1, data);
655          }          } else {
656                    xcf = 4*mvs.x; ycf = 4*mvs.y;
657          switch ( ((b_mvs.x&1)<<1) + (b_mvs.y&1) ) {                  xcb = 4*b_mvs.x; ycb = 4*b_mvs.y;
658                  case 0 : ReferenceB = data->bRef + b_mvs.x/2 + (b_mvs.y/2)*(data->iEdgedWidth); break;                  ReferenceF = GetReference(mvs.x, mvs.y, data);
659                  case 1 : ReferenceB = data->bRefV + b_mvs.x/2 + ((b_mvs.y-1)/2)*(data->iEdgedWidth); break;                  ReferenceB = GetReferenceB(b_mvs.x, b_mvs.y, 1, data);
                 case 2 : ReferenceB = data->bRefH + (b_mvs.x-1)/2 + (b_mvs.y/2)*(data->iEdgedWidth); break;  
                 default : ReferenceB = data->bRefHV + (b_mvs.x-1)/2 + ((b_mvs.y-1)/2)*(data->iEdgedWidth); break;  
660          }          }
661    
662          sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
663            sad += (data->lambda16 * d_mv_bits(x, y, zeroMV, 1, 0, 0) * sad)>>10;
664    
665            if (data->chroma && sad < *data->iMinSAD)
666                    sad += ChromaSAD2((xcf >> 3) + roundtab_76[xcf & 0xf],
667                                                            (ycf >> 3) + roundtab_76[ycf & 0xf],
668                                                            (xcb >> 3) + roundtab_76[xcb & 0xf],
669                                                            (ycb >> 3) + roundtab_76[ycb & 0xf], data);
670    
671          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
672                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
673                  data->currentMV->x = x; data->currentMV->y = y;                  data->currentMV->x = x; data->currentMV->y = y;
674                  *dir = Direction; }                  *dir = Direction;
675  }  }
676    }
677    
678    
679  static void  static void
680  CheckCandidate8(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidateRD16(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
681  {  {
682          int32_t sad;  
683          const uint8_t * Reference;          int16_t *in = data->dctSpace, *coeff = data->dctSpace + 64;
684            int32_t rd = 0;
685            VECTOR * current;
686            const uint8_t * ptr;
687            int i, cbp = 0, t, xc, yc;
688    
689          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
690                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
691    
692          switch ( ((x&1)<<1) + (y&1) )          if (!data->qpel_precision) {
693          {                  ptr = GetReference(x, y, data);
694                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;                  current = data->currentMV;
695                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  xc = x; yc = y;
696                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;          } else { /* x and y are in 1/4 precision */
697                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  ptr = Interpolate16x16qpel(x, y, 0, data);
698                    current = data->currentQMV;
699                    xc = x/2; yc = y/2;
700            }
701    
702            for(i = 0; i < 4; i++) {
703                    int s = 8*((i&1) + (i>>1)*data->iEdgedWidth);
704                    transfer_8to16subro(in, data->Cur + s, ptr + s, data->iEdgedWidth);
705                    rd += data->temp[i] = Block_CalcBits(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, &cbp, i);
706            }
707    
708            rd += t = BITS_MULT*d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
709    
710            if (data->temp[0] + t < data->iMinSAD[1]) {
711                    data->iMinSAD[1] = data->temp[0] + t; current[1].x = x; current[1].y = y; data->cbp[1] = (data->cbp[1]&~32) | cbp&32; }
712            if (data->temp[1] < data->iMinSAD[2]) {
713                    data->iMinSAD[2] = data->temp[1]; current[2].x = x; current[2].y = y; data->cbp[1] = (data->cbp[1]&~16) | cbp&16; }
714            if (data->temp[2] < data->iMinSAD[3]) {
715                    data->iMinSAD[3] = data->temp[2]; current[3].x = x; current[3].y = y; data->cbp[1] = (data->cbp[1]&~8) | cbp&8; }
716            if (data->temp[3] < data->iMinSAD[4]) {
717                    data->iMinSAD[4] = data->temp[3]; current[4].x = x; current[4].y = y; data->cbp[1] = (data->cbp[1]&~4) | cbp&4; }
718    
719            rd += BITS_MULT*xvid_cbpy_tab[15-(cbp>>2)].len;
720    
721            if (rd >= data->iMinSAD[0]) return;
722    
723            /* chroma */
724            xc = (xc >> 1) + roundtab_79[xc & 0x3];
725            yc = (yc >> 1) + roundtab_79[yc & 0x3];
726    
727            /* chroma U */
728            ptr = interpolate8x8_switch2(data->RefQ, data->RefP[4], 0, 0, xc, yc, data->iEdgedWidth/2, data->rounding);
729            transfer_8to16subro(in, data->CurU, ptr, data->iEdgedWidth/2);
730            rd += Block_CalcBits(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, &cbp, 4);
731            if (rd >= data->iMinSAD[0]) return;
732    
733            /* chroma V */
734            ptr = interpolate8x8_switch2(data->RefQ, data->RefP[5], 0, 0, xc, yc, data->iEdgedWidth/2, data->rounding);
735            transfer_8to16subro(in, data->CurV, ptr, data->iEdgedWidth/2);
736            rd += Block_CalcBits(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, &cbp, 5);
737    
738            rd += BITS_MULT*mcbpc_inter_tab[(MODE_INTER & 7) | ((cbp & 3) << 3)].len;
739    
740            if (rd < data->iMinSAD[0]) {
741                    data->iMinSAD[0] = rd;
742                    current[0].x = x; current[0].y = y;
743                    *dir = Direction;
744                    *data->cbp = cbp;
745            }
746          }          }
747    
748          sad = sad8(data->Cur, Reference, data->iEdgedWidth);  static void
749          sad += lambda_vec8[data->iQuant] * d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);  CheckCandidateRD8(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
750    {
751    
752          if (sad < *(data->iMinSAD)) {          int16_t *in = data->dctSpace, *coeff = data->dctSpace + 64;
753                  *(data->iMinSAD) = sad;          int32_t rd;
754                  data->currentMV->x = x; data->currentMV->y = y;          VECTOR * current;
755                  *dir = Direction; }          const uint8_t * ptr;
756            int cbp = 0;
757    
758            if ( (x > data->max_dx) || (x < data->min_dx)
759                    || (y > data->max_dy) || (y < data->min_dy) ) return;
760    
761            if (!data->qpel_precision) {
762                    ptr = GetReference(x, y, data);
763                    current = data->currentMV;
764            } else { /* x and y are in 1/4 precision */
765                    ptr = Interpolate8x8qpel(x, y, 0, 0, data);
766                    current = data->currentQMV;
767            }
768    
769            transfer_8to16subro(in, data->Cur, ptr, data->iEdgedWidth);
770            rd = Block_CalcBits(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, &cbp, 5);
771            rd += BITS_MULT*d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
772    
773            if (rd < data->iMinSAD[0]) {
774                    *data->cbp = cbp;
775                    data->iMinSAD[0] = rd;
776                    current[0].x = x; current[0].y = y;
777                    *dir = Direction;
778            }
779  }  }
780    
781  /* CHECK_CANDIATE FUNCTIONS END */  /* CHECK_CANDIATE FUNCTIONS END */
# Line 348  Line 790 
790    
791                  int iDirection;                  int iDirection;
792    
793                  do {          for(;;) { /* forever */
794                          iDirection = 0;                          iDirection = 0;
795                          if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);                          if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);
796                          if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);                          if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);
# Line 357  Line 799 
799    
800                          /* now we're doing diagonal checks near our candidate */                          /* now we're doing diagonal checks near our candidate */
801    
802                          if (iDirection) {               //checking if anything found                  if (iDirection) {               /* if anything found */
803                                  bDirection = iDirection;                                  bDirection = iDirection;
804                                  iDirection = 0;                                  iDirection = 0;
805                                  x = data->currentMV->x; y = data->currentMV->y;                                  x = data->currentMV->x; y = data->currentMV->y;
806                                  if (bDirection & 3) {   //our candidate is left or right                          if (bDirection & 3) {   /* our candidate is left or right */
807                                          CHECK_CANDIDATE(x, y + iDiamondSize, 8);                                          CHECK_CANDIDATE(x, y + iDiamondSize, 8);
808                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);
809                                  } else {                        // what remains here is up or down                          } else {                        /* what remains here is up or down */
810                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);
811                                          CHECK_CANDIDATE(x - iDiamondSize, y, 1); }                                  CHECK_CANDIDATE(x - iDiamondSize, y, 1);
812                            }
813    
814                                  if (iDirection) {                                  if (iDirection) {
815                                          bDirection += iDirection;                                          bDirection += iDirection;
816                                          x = data->currentMV->x; y = data->currentMV->y; }                                  x = data->currentMV->x; y = data->currentMV->y;
817                          } else {                                //about to quit, eh? not so fast....                          }
818                    } else {                                /* about to quit, eh? not so fast.... */
819                                  switch (bDirection) {                                  switch (bDirection) {
820                                  case 2:                                  case 2:
821                                          CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);                                          CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
# Line 409  Line 853 
853                                          CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);                                          CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
854                                          CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);                                          CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
855                                          break;                                          break;
856                                  default:                //1+2+4+8 == we didn't find anything at all                          default:                /* 1+2+4+8 == we didn't find anything at all */
857                                          CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);                                          CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
858                                          CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);                                          CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
859                                          CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);                                          CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
860                                          CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);                                          CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
861                                          break;                                          break;
862                                  }                                  }
863                                  if (!iDirection) break;         //ok, the end. really                          if (!iDirection) break;         /* ok, the end. really */
864                                  bDirection = iDirection;                                  bDirection = iDirection;
865                                  x = data->currentMV->x; y = data->currentMV->y;                                  x = data->currentMV->x; y = data->currentMV->y;
866                          }                          }
867                  }                  }
                 while (1);                              //forever  
868  }  }
869    
870  static void  static void
# Line 462  Line 905 
905    
906                          /* now we're doing diagonal checks near our candidate */                          /* now we're doing diagonal checks near our candidate */
907    
908                          if (iDirection) {               //checking if anything found                  if (iDirection) {               /* checking if anything found */
909                                  bDirection = iDirection;                                  bDirection = iDirection;
910                                  iDirection = 0;                                  iDirection = 0;
911                                  x = data->currentMV->x; y = data->currentMV->y;                                  x = data->currentMV->x; y = data->currentMV->y;
912                                  if (bDirection & 3) {   //our candidate is left or right                          if (bDirection & 3) {   /* our candidate is left or right */
913                                          CHECK_CANDIDATE(x, y + iDiamondSize, 8);                                          CHECK_CANDIDATE(x, y + iDiamondSize, 8);
914                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);
915                                  } else {                        // what remains here is up or down                          } else {                        /* what remains here is up or down */
916                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);
917                                          CHECK_CANDIDATE(x - iDiamondSize, y, 1); }                                  CHECK_CANDIDATE(x - iDiamondSize, y, 1);
918                            }
919                                  bDirection += iDirection;                                  bDirection += iDirection;
920                                  x = data->currentMV->x; y = data->currentMV->y;                                  x = data->currentMV->x; y = data->currentMV->y;
921                          }                          }
# Line 482  Line 925 
925    
926  /* MAINSEARCH FUNCTIONS END */  /* MAINSEARCH FUNCTIONS END */
927    
 /* HALFPELREFINE COULD BE A MAINSEARCH FUNCTION, BUT THERE IS NO NEED FOR IT */  
   
928  static void  static void
929  HalfpelRefine(const SearchData * const data)  SubpelRefine(const SearchData * const data)
930  {  {
931  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a half-pel or q-pel refinement */
932            const VECTOR centerMV = data->qpel_precision ? *data->currentQMV : *data->currentMV;
933          VECTOR backupMV = *(data->currentMV);          int iDirection; /* only needed because macro expects it */
934          int iDirection; //not needed  
935            CHECK_CANDIDATE(centerMV.x, centerMV.y - 1, 0);
936          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);          CHECK_CANDIDATE(centerMV.x + 1, centerMV.y - 1, 0);
937          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);          CHECK_CANDIDATE(centerMV.x + 1, centerMV.y, 0);
938          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);          CHECK_CANDIDATE(centerMV.x + 1, centerMV.y + 1, 0);
939          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y + 1, 0);          CHECK_CANDIDATE(centerMV.x, centerMV.y + 1, 0);
940            CHECK_CANDIDATE(centerMV.x - 1, centerMV.y + 1, 0);
941          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y, 0);          CHECK_CANDIDATE(centerMV.x - 1, centerMV.y, 0);
942          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y, 0);          CHECK_CANDIDATE(centerMV.x - 1, centerMV.y - 1, 0);
   
         CHECK_CANDIDATE(backupMV.x, backupMV.y + 1, 0);  
         CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);  
943  }  }
944    
945  static __inline int  static __inline int
946  SkipDecisionP(const IMAGE * current, const IMAGE * reference,  SkipDecisionP(const IMAGE * current, const IMAGE * reference,
947                                                          const int x, const int y,                                                          const int x, const int y,
948                                                          const uint32_t iEdgedWidth, const uint32_t iQuant)                                                          const uint32_t stride, const uint32_t iQuant, int rrv)
949    
950  {  {
951  /*      keep repeating checks for all b-frames before this P frame,          int offset = (x + y*stride)*8;
952          to make sure that SKIP is possible (todo)          if(!rrv) {
953          how: if skip is not possible set sad00 to a very high value */                  uint32_t sadC = sad8(current->u + offset,
954                                                    reference->u + offset, stride);
         uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,  
                                         reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);  
955          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
956          sadC += sad8(current->v + x*8 + y*(iEdgedWidth/2)*8,                  sadC += sad8(current->v + offset,
957                                          reference->v + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                                  reference->v + offset, stride);
958          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
959                    return 1;
960    
961            } else {
962                    uint32_t sadC = sad16(current->u + 2*offset,
963                                                    reference->u + 2*offset, stride, 256*4096);
964                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP*4) return 0;
965                    sadC += sad16(current->v + 2*offset,
966                                                    reference->v + 2*offset, stride, 256*4096);
967                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP*4) return 0;
968          return 1;          return 1;
969  }  }
970    }
971    
972  static __inline void  static __inline void
973  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)  ZeroMacroblockP(MACROBLOCK *pMB, const int32_t sad)
974  {  {
975          pMB->mode = MODE_NOT_CODED;          pMB->mode = MODE_INTER;
976          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = zeroMV;
977          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;          pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] = pMB->qmvs[3] = zeroMV;
978          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = sad;          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = sad;
979  }  }
980    
981  bool  static __inline void
982  MotionEstimation(MBParam * const pParam,  ModeDecision(SearchData * const Data,
983                                   FRAMEINFO * const current,                          MACROBLOCK * const pMB,
984                                   FRAMEINFO * const reference,                          const MACROBLOCK * const pMBs,
985                                   const IMAGE * const pRefH,                          const int x, const int y,
986                                   const IMAGE * const pRefV,                          const MBParam * const pParam,
987                                   const IMAGE * const pRefHV,                          const uint32_t MotionFlags,
988                                   const uint32_t iLimit)                          const uint32_t VopFlags,
989  {                          const uint32_t VolFlags,
990          MACROBLOCK *const pMBs = current->mbs;                          const IMAGE * const pCurrent,
991          const IMAGE *const pCurrent = &current->image;                          const IMAGE * const pRef,
992          const IMAGE *const pRef = &reference->image;                          const IMAGE * const vGMC,
993                            const int coding_type)
994          const VECTOR zeroMV = { 0, 0 };  {
995            int mode = MODE_INTER;
996          uint32_t x, y;          int mcsel = 0;
997          uint32_t iIntra = 0;          int inter4v = (VopFlags & XVID_VOP_INTER4V) && (pMB->dquant == 0);
998          int32_t InterBias;          const uint32_t iQuant = pMB->quant;
999    
1000          // some pre-initialized thingies for SearchP          const int skip_possible = (coding_type == P_VOP) && (pMB->dquant == 0);
1001          int32_t temp[5];  
1002          VECTOR currentMV[5];          pMB->mcsel = 0;
1003          int32_t iMinSAD[5];  
1004          SearchData Data;          if (!(VopFlags & XVID_VOP_MODEDECISION_RD)) { /* normal, fast, SAD-based mode decision */
1005          Data.iEdgedWidth = pParam->edged_width;                  int sad;
1006          Data.currentMV = currentMV;                  int InterBias = MV16_INTER_BIAS;
1007          Data.iMinSAD = iMinSAD;                  if (inter4v == 0 || Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
1008          Data.temp = temp;                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant) {
1009          Data.iFcode = current->fcode;                          mode = MODE_INTER;
1010                            sad = Data->iMinSAD[0];
1011                    } else {
1012                            mode = MODE_INTER4V;
1013                            sad = Data->iMinSAD[1] + Data->iMinSAD[2] +
1014                                                    Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant;
1015                            Data->iMinSAD[0] = sad;
1016                    }
1017    
1018          if (sadInit) (*sadInit) ();                  /* final skip decision, a.k.a. "the vector you found, really that good?" */
1019                    if (skip_possible && (pMB->sad16 < (int)iQuant * MAX_SAD00_FOR_SKIP))
1020                            if ( (100*sad)/(pMB->sad16+1) > FINAL_SKIP_THRESH)
1021                                    if (Data->chroma || SkipDecisionP(pCurrent, pRef, x, y, Data->iEdgedWidth/2, iQuant, Data->rrv)) {
1022                                            mode = MODE_NOT_CODED;
1023                                            sad = 0;
1024                                    }
1025    
1026          for (y = 0; y < pParam->mb_height; y++) {                  /* mcsel */
1027                  for (x = 0; x < pParam->mb_width; x++)  {                  if (coding_type == S_VOP) {
1028    
1029                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          int32_t iSAD = sad16(Data->Cur,
1030                          int32_t sad00 =  pMB->sad16                                  vGMC->y + 16*y*Data->iEdgedWidth + 16*x, Data->iEdgedWidth, 65536);
                                 = sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,  
                                                         pRef->y + (x + y * pParam->edged_width) * 16,  
                                                         pParam->edged_width, pMB->sad8 );  
1031    
1032                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (Data->chroma) {
1033                                  pMB->dquant = NO_CHANGE;                                  iSAD += sad8(Data->CurU, vGMC->u + 8*y*(Data->iEdgedWidth/2) + 8*x, Data->iEdgedWidth/2);
1034                                  pMB->quant = current->quant; }                                  iSAD += sad8(Data->CurV, vGMC->v + 8*y*(Data->iEdgedWidth/2) + 8*x, Data->iEdgedWidth/2);
   
 //initial skip decision  
   
                         if ((pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)  
                                 && (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) ) {  
                                 if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {  
                                                 SkipMacroblockP(pMB, sad00);  
                                                 continue;  
1035                                  }                                  }
                         } else sad00 = 256*4096; // skip not allowed - for final skip decision  
1036    
1037                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          if (iSAD <= sad) {              /* mode decision GMC */
1038                                                  y, current->motion_flags, pMB->quant,                                  mode = MODE_INTER;
1039                                                  &Data, pParam, pMBs, reference->mbs,                                  mcsel = 1;
1040                                                  current->global_flags & XVID_INTER4V, pMB);                                  sad = iSAD;
1041                            }
1042    
1043  /* final skip decision, a.k.a. "the vector you found, really that good?" */                  }
                         if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)  
                                 if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)  
                                 { SkipMacroblockP(pMB, sad00); continue; }  
1044    
1045  /* finally, intra decision */                  /* intra decision */
1046    
1047                          InterBias = MV16_INTER_BIAS;                  if (iQuant > 8) InterBias += 100 * (iQuant - 8); /* to make high quants work */
                         if (pMB->quant > 8)  InterBias += 50 * (pMB->quant - 8); // to make high quants work  
1048                          if (y != 0)                          if (y != 0)
1049                                  if ((pMB - pParam->mb_width)->mode == MODE_INTER ) InterBias -= 50;                          if ((pMB - pParam->mb_width)->mode == MODE_INTRA ) InterBias -= 80;
1050                          if (x != 0)                          if (x != 0)
1051                                  if ((pMB - 1)->mode == MODE_INTER ) InterBias -= 50;                          if ((pMB - 1)->mode == MODE_INTRA ) InterBias -= 80;
1052    
1053                          if (InterBias < pMB->sad16)  {                  if (Data->chroma) InterBias += 50; /* dev8(chroma) ??? <-- yes, we need dev8 (no big difference though) */
1054                                  const int32_t deviation =                  if (Data->rrv) InterBias *= 4;
                                         dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,  
                                                   pParam->edged_width);  
1055    
1056                                  if (deviation < (pMB->sad16 - InterBias)) {                  if (InterBias < sad) {
1057                                          if (++iIntra >= iLimit) return 1;                          int32_t deviation;
1058                                          pMB->mode = MODE_INTRA;                          if (!Data->rrv)
1059                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =                                  deviation = dev16(Data->Cur, Data->iEdgedWidth);
1060                                                          pMB->mvs[3] = zeroMV;                          else
1061                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =                                  deviation = dev16(Data->Cur, Data->iEdgedWidth) + /* dev32() */
1062                                                  pMB->sad8[3] = 0;                                                          dev16(Data->Cur+16, Data->iEdgedWidth) +
1063                                  }                                                          dev16(Data->Cur + 16*Data->iEdgedWidth, Data->iEdgedWidth) +
1064                          }                                                          dev16(Data->Cur+16+16*Data->iEdgedWidth, Data->iEdgedWidth);
1065                  }  
1066                            if (deviation < (sad - InterBias)) mode = MODE_INTRA;
1067                    }
1068    
1069                    pMB->cbp = 63;
1070                    pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = sad;
1071    
1072            } else { /* Rate-Distortion */
1073    
1074                    int min_rd, intra_rd, i, cbp, c[2] = {0, 0};
1075                    VECTOR backup[5], *v;
1076                    Data->iQuant = iQuant;
1077                    Data->cbp = c;
1078    
1079                    v = Data->qpel ? Data->currentQMV : Data->currentMV;
1080                    for (i = 0; i < 5; i++) {
1081                            Data->iMinSAD[i] = 256*4096;
1082                            backup[i] = v[i];
1083                    }
1084    
1085                    min_rd = findRDinter(Data, pMBs, x, y, pParam, MotionFlags);
1086                    cbp = *Data->cbp;
1087    
1088                    if (coding_type == S_VOP) {
1089                            int gmc_rd;
1090                            *Data->iMinSAD = min_rd += BITS_MULT*1; /* mcsel */
1091                            gmc_rd = findRDgmc(Data, vGMC, x, y);
1092                            if (gmc_rd < min_rd) {
1093                                    mcsel = 1;
1094                                    *Data->iMinSAD = min_rd = gmc_rd;
1095                                    mode = MODE_INTER;
1096                                    cbp = *Data->cbp;
1097                            }
1098                    }
1099    
1100                    if (inter4v) {
1101                            int v4_rd;
1102                            v4_rd = findRDinter4v(Data, pMB, pMBs, x, y, pParam, MotionFlags, backup);
1103                            if (v4_rd < min_rd) {
1104                                    Data->iMinSAD[0] = min_rd = v4_rd;
1105                                    mode = MODE_INTER4V;
1106                                    cbp = *Data->cbp;
1107                            }
1108                    }
1109    
1110                    intra_rd = findRDintra(Data);
1111                    if (intra_rd < min_rd) {
1112                            *Data->iMinSAD = min_rd = intra_rd;
1113                            mode = MODE_INTRA;
1114                    }
1115    
1116                    pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;
1117                    pMB->cbp = cbp;
1118            }
1119    
1120            if (Data->rrv) {
1121                            Data->currentMV[0].x = RRV_MV_SCALEDOWN(Data->currentMV[0].x);
1122                            Data->currentMV[0].y = RRV_MV_SCALEDOWN(Data->currentMV[0].y);
1123            }
1124    
1125            if (mode == MODE_INTER && mcsel == 0) {
1126                    pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1127    
1128                    if(Data->qpel) {
1129                            pMB->qmvs[0] = pMB->qmvs[1]
1130                                    = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1131                            pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predMV.x;
1132                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predMV.y;
1133                    } else {
1134                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1135                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1136                    }
1137    
1138            } else if (mode == MODE_INTER ) { // but mcsel == 1
1139    
1140                    pMB->mcsel = 1;
1141                    if (Data->qpel) {
1142                            pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] = pMB->qmvs[3] = pMB->amv;
1143                            pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = pMB->amv.x/2;
1144                            pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = pMB->amv.y/2;
1145                    } else
1146                            pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->amv;
1147    
1148            } else
1149                    if (mode == MODE_INTER4V) ; /* anything here? */
1150            else    /* INTRA, NOT_CODED */
1151                    ZeroMacroblockP(pMB, 0);
1152    
1153            pMB->mode = mode;
1154    }
1155    
1156    bool
1157    MotionEstimation(MBParam * const pParam,
1158                                     FRAMEINFO * const current,
1159                                     FRAMEINFO * const reference,
1160                                     const IMAGE * const pRefH,
1161                                     const IMAGE * const pRefV,
1162                                     const IMAGE * const pRefHV,
1163                                    const IMAGE * const pGMC,
1164                                     const uint32_t iLimit)
1165    {
1166            MACROBLOCK *const pMBs = current->mbs;
1167            const IMAGE *const pCurrent = &current->image;
1168            const IMAGE *const pRef = &reference->image;
1169    
1170            uint32_t mb_width = pParam->mb_width;
1171            uint32_t mb_height = pParam->mb_height;
1172            const uint32_t iEdgedWidth = pParam->edged_width;
1173            const uint32_t MotionFlags = MakeGoodMotionFlags(current->motion_flags, current->vop_flags, current->vol_flags);
1174    
1175            uint32_t x, y;
1176            uint32_t iIntra = 0;
1177            int32_t sad00;
1178            int skip_thresh = INITIAL_SKIP_THRESH * \
1179                    (current->vop_flags & XVID_VOP_REDUCED ? 4:1) * \
1180                    (current->vop_flags & XVID_VOP_MODEDECISION_RD ? 2:1);
1181    
1182            /* some pre-initialized thingies for SearchP */
1183            int32_t temp[8];
1184            VECTOR currentMV[5];
1185            VECTOR currentQMV[5];
1186            int32_t iMinSAD[5];
1187            DECLARE_ALIGNED_MATRIX(dct_space, 3, 64, int16_t, CACHE_LINE);
1188            SearchData Data;
1189            memset(&Data, 0, sizeof(SearchData));
1190            Data.iEdgedWidth = iEdgedWidth;
1191            Data.currentMV = currentMV;
1192            Data.currentQMV = currentQMV;
1193            Data.iMinSAD = iMinSAD;
1194            Data.temp = temp;
1195            Data.iFcode = current->fcode;
1196            Data.rounding = pParam->m_rounding_type;
1197            Data.qpel = (current->vol_flags & XVID_VOL_QUARTERPEL ? 1:0);
1198            Data.chroma = MotionFlags & XVID_ME_CHROMA_PVOP;
1199            Data.rrv = (current->vop_flags & XVID_VOP_REDUCED) ? 1:0;
1200            Data.dctSpace = dct_space;
1201            Data.quant_type = !(pParam->vol_flags & XVID_VOL_MPEGQUANT);
1202    
1203            if ((current->vop_flags & XVID_VOP_REDUCED)) {
1204                    mb_width = (pParam->width + 31) / 32;
1205                    mb_height = (pParam->height + 31) / 32;
1206                    Data.qpel = 0;
1207            }
1208    
1209            Data.RefQ = pRefV->u; /* a good place, also used in MC (for similar purpose) */
1210            if (sadInit) (*sadInit) ();
1211    
1212            for (y = 0; y < mb_height; y++) {
1213                    for (x = 0; x < mb_width; x++)  {
1214                            MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
1215    
1216                            if (!Data.rrv) pMB->sad16 =
1217                                    sad16v(pCurrent->y + (x + y * iEdgedWidth) * 16,
1218                                                            pRef->y + (x + y * iEdgedWidth) * 16,
1219                                                            pParam->edged_width, pMB->sad8 );
1220    
1221                            else pMB->sad16 =
1222                                    sad32v_c(pCurrent->y + (x + y * iEdgedWidth) * 32,
1223                                                            pRef->y + (x + y * iEdgedWidth) * 32,
1224                                                            pParam->edged_width, pMB->sad8 );
1225    
1226                            if (Data.chroma) {
1227                                    Data.temp[7] = sad8(pCurrent->u + x*8 + y*(iEdgedWidth/2)*8,
1228                                                                            pRef->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2)
1229                                                                    + sad8(pCurrent->v + (x + y*(iEdgedWidth/2))*8,
1230                                                                            pRef->v + (x + y*(iEdgedWidth/2))*8, iEdgedWidth/2);
1231                                    pMB->sad16 += Data.temp[7];
1232                            }
1233    
1234                            sad00 = pMB->sad16;
1235    
1236                            /* initial skip decision */
1237                            /* no early skip for GMC (global vector = skip vector is unknown!)  */
1238                            if (current->coding_type != S_VOP)      { /* no fast SKIP for S(GMC)-VOPs */
1239                                    if (pMB->dquant == 0 && sad00 < pMB->quant * skip_thresh)
1240                                            if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, iEdgedWidth/2, pMB->quant, Data.rrv)) {
1241                                                    ZeroMacroblockP(pMB, sad00);
1242                                                    pMB->mode = MODE_NOT_CODED;
1243                                                    continue;
1244          }          }
         return 0;  
1245  }  }
1246    
1247                            if ((current->vop_flags & XVID_VOP_CARTOON) &&
1248                                    (sad00 < pMB->quant * 4 * skip_thresh)) { /* favorize (0,0) vector for cartoons */
1249                                    ZeroMacroblockP(pMB, sad00);
1250                                    continue;
1251                            }
1252    
1253                            SearchP(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
1254                                            y, MotionFlags, current->vop_flags, current->vol_flags,
1255                                            &Data, pParam, pMBs, reference->mbs, pMB);
1256    
1257                            ModeDecision(&Data, pMB, pMBs, x, y, pParam,
1258                                                     MotionFlags, current->vop_flags, current->vol_flags,
1259                                                     pCurrent, pRef, pGMC, current->coding_type);
1260    
1261                            if (pMB->mode == MODE_INTRA)
1262                                    if (++iIntra > iLimit) return 1;
1263                    }
1264            }
1265    
1266            return 0;
1267    }
1268    
 #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  
1269    
1270  static __inline int  static __inline int
1271  make_mask(const VECTOR * const pmv, const int i)  make_mask(const VECTOR * const pmv, const int i)
1272  {  {
1273          int mask = 255, j;          int mask = 255, j;
1274          for (j = 0; j < i; j++) {          for (j = 0; j < i; j++) {
1275                  if (MVequal(pmv[i], pmv[j])) return 0; // same vector has been checked already                  if (MVequal(pmv[i], pmv[j])) return 0; /* same vector has been checked already */
1276                  if (pmv[i].x == pmv[j].x) {                  if (pmv[i].x == pmv[j].x) {
1277                          if (pmv[i].y == pmv[j].y + iDiamondSize) { mask &= ~4; continue; }                          if (pmv[i].y == pmv[j].y + iDiamondSize) mask &= ~4;
1278                          if (pmv[i].y == pmv[j].y - iDiamondSize) { mask &= ~8; continue; }                          else if (pmv[i].y == pmv[j].y - iDiamondSize) mask &= ~8;
1279                  } else                  } else
1280                          if (pmv[i].y == pmv[j].y) {                          if (pmv[i].y == pmv[j].y) {
1281                                  if (pmv[i].x == pmv[j].x + iDiamondSize) { mask &= ~1; continue; }                                  if (pmv[i].x == pmv[j].x + iDiamondSize) mask &= ~1;
1282                                  if (pmv[i].x == pmv[j].x - iDiamondSize) { mask &= ~2; continue; }                                  else if (pmv[i].x == pmv[j].x - iDiamondSize) mask &= ~2;
1283                          }                          }
1284          }          }
1285          return mask;          return mask;
1286  }  }
1287    
1288  static __inline void  static __inline void
1289  PreparePredictionsP(VECTOR * const pmv, int x, int y, const int iWcount,  PreparePredictionsP(VECTOR * const pmv, int x, int y, int iWcount,
1290                          const int iHcount, const MACROBLOCK * const prevMB)                          int iHcount, const MACROBLOCK * const prevMB, int rrv)
1291  {  {
1292            /* this function depends on get_pmvdata which means that it sucks. It should get the predictions by itself */
1293            if (rrv) { iWcount /= 2; iHcount /= 2; }
1294    
1295  //this function depends on get_pmvdata which means that it sucks. It should get the predictions by itself          if ( (y != 0) && (x < (iWcount-1)) ) {          /* [5] top-right neighbour */
   
         if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour  
1296                  pmv[5].x = EVEN(pmv[3].x);                  pmv[5].x = EVEN(pmv[3].x);
1297                  pmv[5].y = EVEN(pmv[3].y);                  pmv[5].y = EVEN(pmv[3].y);
1298          } else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
1299    
1300          if (x != 0) { pmv[3].x = EVEN(pmv[1].x); pmv[3].y = EVEN(pmv[1].y); }// pmv[3] is left neighbour          if (x != 0) { pmv[3].x = EVEN(pmv[1].x); pmv[3].y = EVEN(pmv[1].y); }/* pmv[3] is left neighbour */
1301          else pmv[3].x = pmv[3].y = 0;          else pmv[3].x = pmv[3].y = 0;
1302    
1303          if (y != 0) { pmv[4].x = EVEN(pmv[2].x); pmv[4].y = EVEN(pmv[2].y); }// [4] top neighbour          if (y != 0) { pmv[4].x = EVEN(pmv[2].x); pmv[4].y = EVEN(pmv[2].y); }/* [4] top neighbour */
1304      else pmv[4].x = pmv[4].y = 0;      else pmv[4].x = pmv[4].y = 0;
1305    
1306          // [1] median prediction          /* [1] median prediction */
1307          pmv[1].x = EVEN(pmv[0].x); pmv[1].y = EVEN(pmv[0].y);          pmv[1].x = EVEN(pmv[0].x); pmv[1].y = EVEN(pmv[0].y);
1308    
1309          pmv[0].x = pmv[0].y = 0; // [0] is zero; not used in the loop (checked before) but needed here for make_mask          pmv[0].x = pmv[0].y = 0; /* [0] is zero; not used in the loop (checked before) but needed here for make_mask */
1310    
1311          pmv[2].x = EVEN(prevMB->mvs[0].x); // [2] is last frame          pmv[2].x = EVEN(prevMB->mvs[0].x); /* [2] is last frame */
1312          pmv[2].y = EVEN(prevMB->mvs[0].y);          pmv[2].y = EVEN(prevMB->mvs[0].y);
1313    
1314          if ((x != iWcount-1) && (y != iHcount-1)) {          if ((x < iWcount-1) && (y < iHcount-1)) {
1315                  pmv[6].x = EVEN((prevMB+1+iWcount)->mvs[0].x); //[6] right-down neighbour in last frame                  pmv[6].x = EVEN((prevMB+1+iWcount)->mvs[0].x); /* [6] right-down neighbour in last frame */
1316                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
1317          } else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
1318    
1319            if (rrv) {
1320                    int i;
1321                    for (i = 0; i < 7; i++) {
1322                            pmv[i].x = RRV_MV_SCALEUP(pmv[i].x);
1323                            pmv[i].y = RRV_MV_SCALEUP(pmv[i].y);
1324                    }
1325            }
1326  }  }
1327    
1328  static void  static void
1329  SearchP(const uint8_t * const pRef,  SearchP(const IMAGE * const pRef,
1330                  const uint8_t * const pRefH,                  const uint8_t * const pRefH,
1331                  const uint8_t * const pRefV,                  const uint8_t * const pRefV,
1332                  const uint8_t * const pRefHV,                  const uint8_t * const pRefHV,
# Line 688  Line 1334 
1334                  const int x,                  const int x,
1335                  const int y,                  const int y,
1336                  const uint32_t MotionFlags,                  const uint32_t MotionFlags,
1337                  const uint32_t iQuant,                  const uint32_t VopFlags,
1338                    const uint32_t VolFlags,
1339                  SearchData * const Data,                  SearchData * const Data,
1340                  const MBParam * const pParam,                  const MBParam * const pParam,
1341                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
1342                  const MACROBLOCK * const prevMBs,                  const MACROBLOCK * const prevMBs,
                 int inter4v,  
1343                  MACROBLOCK * const pMB)                  MACROBLOCK * const pMB)
1344  {  {
1345    
1346          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
1347          VECTOR pmv[7];          VECTOR pmv[7];
1348            int inter4v = (VopFlags & XVID_VOP_INTER4V) && (pMB->dquant == 0);
1349    
         get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()  
1350          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1351                                  pParam->width, pParam->height, Data->iFcode);                                                  pParam->width, pParam->height, Data->iFcode - Data->qpel, 0, Data->rrv);
   
         Data->predMV = pmv[0];  
         Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;  
         Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;  
         Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;  
         Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;  
         Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;  
   
         Data->iQuant = iQuant;  
   
         if (!(MotionFlags & PMV_HALFPEL16)) {  
                 Data->min_dx = EVEN(Data->min_dx);  
                 Data->max_dx = EVEN(Data->max_dx);  
                 Data->min_dy = EVEN(Data->min_dy);  
                 Data->max_dy = EVEN(Data->max_dy); }  
   
         for(i = 0;  i < 5; i++) Data->iMinSAD[i] = 256*4096;  
   
         if (inter4v) CheckCandidate = CheckCandidate16;  
         else CheckCandidate = CheckCandidate16no4v;  
   
         (*CheckCandidate)(Data->predMV.x, Data->predMV.y, 0, &iDirection, Data);  
1352    
1353          for(i = 0;  i < 5; i++) Data->currentMV[i].x = Data->currentMV[i].y = 0;          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);
1354    
1355          i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);          Data->temp[5] = Data->temp[6] = 0; /* chroma-sad cache */
1356          Data->iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;          i = Data->rrv ? 2 : 1;
1357          Data->iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16*i;
1358            Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
1359            Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
1360    
1361            Data->RefP[0] = pRef->y + (x + Data->iEdgedWidth*y) * 16*i;
1362            Data->RefP[2] = pRefH + (x + Data->iEdgedWidth*y) * 16*i;
1363            Data->RefP[1] = pRefV + (x + Data->iEdgedWidth*y) * 16*i;
1364            Data->RefP[3] = pRefHV + (x + Data->iEdgedWidth*y) * 16*i;
1365            Data->RefP[4] = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
1366            Data->RefP[5] = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
1367    
1368            Data->lambda16 = lambda_vec16[pMB->quant];
1369            Data->lambda8 = lambda_vec8[pMB->quant];
1370            Data->qpel_precision = 0;
1371    
1372            memset(Data->currentMV, 0, 5*sizeof(VECTOR));
1373    
1374            if (Data->qpel) Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1375            else Data->predMV = pmv[0];
1376    
1377            i = d_mv_bits(0, 0, Data->predMV, Data->iFcode, 0, 0);
1378            Data->iMinSAD[0] = pMB->sad16 + ((Data->lambda16 * i * pMB->sad16)>>10);
1379            Data->iMinSAD[1] = pMB->sad8[0] + ((Data->lambda8 * i * (pMB->sad8[0]+NEIGH_8X8_BIAS)) >> 10);
1380          Data->iMinSAD[2] = pMB->sad8[1];          Data->iMinSAD[2] = pMB->sad8[1];
1381          Data->iMinSAD[3] = pMB->sad8[2];          Data->iMinSAD[3] = pMB->sad8[2];
1382          Data->iMinSAD[4] = pMB->sad8[3];          Data->iMinSAD[4] = pMB->sad8[3];
1383    
1384          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if ((!(VopFlags & XVID_VOP_MODEDECISION_RD)) && (x | y)) {
1385                    threshA = Data->temp[0]; /* that's where we keep this SAD atm */
         if ((x == 0) && (y == 0)) threshA = 512;  
         else {  
                 threshA = Data->temp[0] + 20;  
1386                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
1387                  if (threshA > 1024) threshA = 1024; }                  else if (threshA > 1024) threshA = 1024;
1388            } else
1389                    threshA = 512;
1390    
1391          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,
1392                                          prevMBs + x + y * pParam->mb_width);                                          prevMBs + x + y * pParam->mb_width, Data->rrv);
1393    
1394  /* main loop. checking all predictions */          if (!Data->rrv) {
1395                    if (inter4v | Data->chroma) CheckCandidate = CheckCandidate16;
1396                            else CheckCandidate = CheckCandidate16no4v; /* for extra speed */
1397            } else CheckCandidate = CheckCandidate32;
1398    
1399    /* main loop. checking all predictions (but first, which is 0,0 and has been checked in MotionEstimation())*/
1400    
1401          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
1402                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1403                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, Data);                  CheckCandidate(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1404                  if (Data->iMinSAD[0] <= threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1405          }          }
1406    
1407          if ((Data->iMinSAD[0] <= threshA) ||          if ((Data->iMinSAD[0] <= threshA) ||
1408                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
1409                          (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {                          (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16)))
1410                  inter4v = 0;                  inter4v = 0;
1411          } else {          else {
1412    
1413                  MainSearchFunc * MainSearchPtr;                  MainSearchFunc * MainSearchPtr;
1414                  if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;                  if (MotionFlags & XVID_ME_USESQUARES16) MainSearchPtr = SquareSearch;
1415                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & XVID_ME_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1416                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1417    
1418                  (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);                  MainSearchPtr(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1419    
1420  /* extended search, diamond starting in 0,0 and in prediction.  /* extended search, diamond starting in 0,0 and in prediction.
1421          note that this search is/might be done in halfpel positions,          note that this search is/might be done in halfpel positions,
1422          which makes it more different than the diamond above */          which makes it more different than the diamond above */
1423    
1424                  if (MotionFlags & PMV_EXTSEARCH16) {                  if (MotionFlags & XVID_ME_EXTSEARCH16) {
1425                          int32_t bSAD;                          int32_t bSAD;
1426                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
1427                          if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?                          if (Data->rrv) {
1428                                  startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);                                  startMV.x = RRV_MV_SCALEUP(startMV.x);
1429                                    startMV.y = RRV_MV_SCALEUP(startMV.y);
1430                            }
1431                          if (!(MVequal(startMV, backupMV))) {                          if (!(MVequal(startMV, backupMV))) {
1432                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1433    
1434                                  CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, Data);                                  CheckCandidate(startMV.x, startMV.y, 255, &iDirection, Data);
1435                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);                                  MainSearchPtr(startMV.x, startMV.y, Data, 255);
1436                                  if (bSAD < Data->iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1437                                          Data->currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1438                                          Data->iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1439                          }                          }
1440    
1441                          backupMV = Data->currentMV[0];                          backupMV = Data->currentMV[0];
1442                          if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;                          startMV.x = startMV.y = 1;
                         else startMV.x = startMV.y = 0;  
1443                          if (!(MVequal(startMV, backupMV))) {                          if (!(MVequal(startMV, backupMV))) {
1444                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1445    
1446                                  CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, Data);                                  CheckCandidate(startMV.x, startMV.y, 255, &iDirection, Data);
1447                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);                                  MainSearchPtr(startMV.x, startMV.y, Data, 255);
1448                                  if (bSAD < Data->iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1449                                          Data->currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1450                                          Data->iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
# Line 801  Line 1452 
1452                  }                  }
1453          }          }
1454    
1455          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);          if (MotionFlags & XVID_ME_HALFPELREFINE16)
1456                            SubpelRefine(Data);
1457    
1458            for(i = 0; i < 5; i++) {
1459                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; /* initialize qpel vectors */
1460                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1461            }
1462    
1463            if (Data->qpel) {
1464                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1465                                    pParam->width, pParam->height, Data->iFcode, 1, 0);
1466                    Data->qpel_precision = 1;
1467                    if (MotionFlags & XVID_ME_QUARTERPELREFINE16)
1468                            SubpelRefine(Data);
1469            }
1470    
1471            if (Data->iMinSAD[0] < (int32_t)pMB->quant * 30)
1472                    inter4v = 0;
1473    
1474          if (inter4v) {          if (inter4v) {
1475                  SearchData Data8;                  SearchData Data8;
1476                  Data8.iFcode = Data->iFcode;                  memcpy(&Data8, Data, sizeof(SearchData)); /* quick copy of common data */
1477                  Data8.iQuant = Data->iQuant;  
                 Data8.iEdgedWidth = Data->iEdgedWidth;  
1478                  Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);                  Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1479                  Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);                  Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1480                  Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);                  Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1481                  Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);                  Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
         }  
   
         if (!(inter4v) ||  
                 (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +  
                         Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {  
 // INTER MODE  
                 pMB->mode = MODE_INTER;  
                 pMB->mvs[0] = pMB->mvs[1]  
                         = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];  
1482    
1483                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  if ((Data->chroma) && (!(VopFlags & XVID_VOP_MODEDECISION_RD))) {
1484                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];                          /* chroma is only used for comparsion to INTER. if the comparsion will be done in BITS domain, it will not be used */
1485                            int sumx = 0, sumy = 0;
1486    
1487                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;                          if (Data->qpel)
1488                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;                                  for (i = 1; i < 5; i++) {
1489          } else {                                          sumx += Data->currentQMV[i].x/2;
1490  // INTER4V MODE; all other things are already set in Search8                                          sumy += Data->currentQMV[i].y/2;
1491                  pMB->mode = MODE_INTER4V;                                  }
1492                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +                          else
1493                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;                                  for (i = 1; i < 5; i++) {
1494                                            sumx += Data->currentMV[i].x;
1495                                            sumy += Data->currentMV[i].y;
1496          }          }
1497    
1498                            Data->iMinSAD[1] += ChromaSAD(  (sumx >> 3) + roundtab_76[sumx & 0xf],
1499                                                                                            (sumy >> 3) + roundtab_76[sumy & 0xf], Data);
1500                    }
1501            } else Data->iMinSAD[1] = 4096*256;
1502  }  }
1503    
1504  static void  static void
# Line 846  Line 1511 
1511                  const int block,                  const int block,
1512                  SearchData * const Data)                  SearchData * const Data)
1513  {  {
1514          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          int i = 0;
1515          Data->iMinSAD = OldData->iMinSAD + 1 + block;          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1516          Data->currentMV = OldData->currentMV + 1 + block;          Data->currentMV = OldData->currentMV + 1 + block;
1517            Data->currentQMV = OldData->currentQMV + 1 + block;
1518    
1519            if(Data->qpel) {
1520                    Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2, y/2, block);
1521                    if (block != 0) i = d_mv_bits(  Data->currentQMV->x, Data->currentQMV->y,
1522                                                                                    Data->predMV, Data->iFcode, 0, 0);
1523            } else {
1524                    Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2, y/2, block);
1525                    if (block != 0) i = d_mv_bits(  Data->currentMV->x, Data->currentMV->y,
1526                                                                                    Data->predMV, Data->iFcode, 0, Data->rrv);
1527            }
1528    
1529            *(Data->iMinSAD) += (Data->lambda8 * i * (*Data->iMinSAD + NEIGH_8X8_BIAS))>>10;
1530    
1531          if (block != 0)          if (MotionFlags & (XVID_ME_EXTSEARCH8|XVID_ME_HALFPELREFINE8|XVID_ME_QUARTERPELREFINE8)) {
                 *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *  
                                                                 d_mv_bits(      Data->currentMV->x - Data->predMV.x,  
                                                                                         Data->currentMV->y - Data->predMV.y,  
                                                                                         Data->iFcode);  
   
         if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {  
   
                 Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));  
                 Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));  
                 Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));  
                 Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));  
1532    
1533                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                  if (Data->rrv) i = 16; else i = 8;
1534    
1535                    Data->RefP[0] = OldData->RefP[0] + i * ((block&1) + Data->iEdgedWidth*(block>>1));
1536                    Data->RefP[1] = OldData->RefP[1] + i * ((block&1) + Data->iEdgedWidth*(block>>1));
1537                    Data->RefP[2] = OldData->RefP[2] + i * ((block&1) + Data->iEdgedWidth*(block>>1));
1538                    Data->RefP[3] = OldData->RefP[3] + i * ((block&1) + Data->iEdgedWidth*(block>>1));
1539    
1540                    Data->Cur = OldData->Cur + i * ((block&1) + Data->iEdgedWidth*(block>>1));
1541                    Data->qpel_precision = 0;
1542    
1543                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1544                                  pParam->width, pParam->height, OldData->iFcode);                                          pParam->width, pParam->height, Data->iFcode - Data->qpel, 0, Data->rrv);
1545    
1546                  CheckCandidate = CheckCandidate8;                  if (!Data->rrv) CheckCandidate = CheckCandidate8;
1547                    else CheckCandidate = CheckCandidate16no4v;
1548    
1549                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & XVID_ME_EXTSEARCH8 && (!(MotionFlags & XVID_ME_EXTSEARCH_RD))) {
1550                            int32_t temp_sad = *(Data->iMinSAD); /* store current MinSAD */
1551    
1552                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1553                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & XVID_ME_USESQUARES8) MainSearchPtr = SquareSearch;
1554                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & XVID_ME_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1555                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1556    
1557                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);    }                          MainSearchPtr(Data->currentMV->x, Data->currentMV->y, Data, 255);
1558    
1559                            if(*(Data->iMinSAD) < temp_sad) {
1560                                            Data->currentQMV->x = 2 * Data->currentMV->x; /* update our qpel vector */
1561                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1562                            }
1563                    }
1564    
1565                    if (MotionFlags & XVID_ME_HALFPELREFINE8) {
1566                            int32_t temp_sad = *(Data->iMinSAD); /* store current MinSAD */
1567    
1568                            SubpelRefine(Data); /* perform halfpel refine of current best vector */
1569    
1570                            if(*(Data->iMinSAD) < temp_sad) { /* we have found a better match */
1571                                    Data->currentQMV->x = 2 * Data->currentMV->x; /* update our qpel vector */
1572                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1573                            }
1574                    }
1575    
1576                    if (Data->qpel && MotionFlags & XVID_ME_QUARTERPELREFINE8) {
1577                                    Data->qpel_precision = 1;
1578                                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1579                                            pParam->width, pParam->height, Data->iFcode, 1, 0);
1580                                    SubpelRefine(Data);
1581                    }
1582            }
1583    
1584                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(Data);          if (Data->rrv) {
1585                            Data->currentMV->x = RRV_MV_SCALEDOWN(Data->currentMV->x);
1586                            Data->currentMV->y = RRV_MV_SCALEDOWN(Data->currentMV->y);
1587          }          }
1588    
1589            if(Data->qpel) {
1590                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predMV.x;
1591                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predMV.y;
1592                    pMB->qmvs[block] = *Data->currentQMV;
1593            } else {
1594          pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;          pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1595          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1596          pMB->mvs[block] = *(Data->currentMV);          }
         pMB->sad8[block] =  4 * (*Data->iMinSAD);  
1597    
1598            pMB->mvs[block] = *Data->currentMV;
1599            pMB->sad8[block] = 4 * *Data->iMinSAD;
1600  }  }
1601    
1602  /* B-frames code starts here */  /* motion estimation for B-frames */
1603    
1604  static __inline VECTOR  static __inline VECTOR
1605  ChoosePred(const MACROBLOCK * const pMB, const uint32_t mode)  ChoosePred(const MACROBLOCK * const pMB, const uint32_t mode)
1606  {  {
1607  /* the stupidiest function ever */  /* the stupidiest function ever */
1608          if (mode == MODE_FORWARD) return pMB->mvs[0];          return (mode == MODE_FORWARD ? pMB->mvs[0] : pMB->b_mvs[0]);
         else return pMB->b_mvs[0];  
1609  }  }
1610    
1611  static void __inline  static void __inline
# Line 906  Line 1615 
1615                                                          const uint32_t mode_curr)                                                          const uint32_t mode_curr)
1616  {  {
1617    
1618          // [0] is prediction          /* [0] is prediction */
1619          pmv[0].x = EVEN(pmv[0].x); pmv[0].y = EVEN(pmv[0].y);          pmv[0].x = EVEN(pmv[0].x); pmv[0].y = EVEN(pmv[0].y);
1620    
1621          pmv[1].x = pmv[1].y = 0; // [1] is zero          pmv[1].x = pmv[1].y = 0; /* [1] is zero */
1622    
1623          pmv[2] = ChoosePred(pMB, mode_curr);          pmv[2] = ChoosePred(pMB, mode_curr);
1624          pmv[2].x = EVEN(pmv[2].x); pmv[2].y = EVEN(pmv[2].y);          pmv[2].x = EVEN(pmv[2].x); pmv[2].y = EVEN(pmv[2].y);
1625    
1626          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour          if ((y != 0)&&(x != (int)(iWcount+1))) {                        /* [3] top-right neighbour */
1627                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);
1628                  pmv[3].x = EVEN(pmv[3].x); pmv[3].y = EVEN(pmv[3].y);                  pmv[3].x = EVEN(pmv[3].x); pmv[3].y = EVEN(pmv[3].y);
1629          } else pmv[3].x = pmv[3].y = 0;          } else pmv[3].x = pmv[3].y = 0;
# Line 929  Line 1638 
1638                  pmv[5].x = EVEN(pmv[5].x); pmv[5].y = EVEN(pmv[5].y);                  pmv[5].x = EVEN(pmv[5].x); pmv[5].y = EVEN(pmv[5].y);
1639          } else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
1640    
1641          if ((x != 0)&&(y != 0)) {          if (x != 0 && y != 0) {
1642                  pmv[6] = ChoosePred(pMB-1-iWcount, mode_curr);                  pmv[6] = ChoosePred(pMB-1-iWcount, mode_curr);
1643                  pmv[6].x = EVEN(pmv[5].x); pmv[5].y = EVEN(pmv[5].y);                  pmv[6].x = EVEN(pmv[6].x); pmv[6].y = EVEN(pmv[6].y);
1644          } else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
   
 // more?  
1645  }  }
1646    
1647    
1648  /* search backward or forward, for b-frames */  /* search backward or forward */
1649  static void  static void
1650  SearchBF(       const uint8_t * const pRef,  SearchBF(       const IMAGE * const pRef,
1651                          const uint8_t * const pRefH,                          const uint8_t * const pRefH,
1652                          const uint8_t * const pRefV,                          const uint8_t * const pRefV,
1653                          const uint8_t * const pRefHV,                          const uint8_t * const pRefHV,
1654                          const IMAGE * const pCur,                          const IMAGE * const pCur,
1655                          const int x, const int y,                          const int x, const int y,
1656                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
1657                          const uint32_t iFcode,                          const uint32_t iFcode,
1658                          const MBParam * const pParam,                          const MBParam * const pParam,
1659                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
1660                          const VECTOR * const predMV,                          const VECTOR * const predMV,
1661                          int32_t * const best_sad,                          int32_t * const best_sad,
1662                          const int32_t mode_current)                          const int32_t mode_current,
1663                            SearchData * const Data)
1664  {  {
1665    
1666          const int32_t iEdgedWidth = pParam->edged_width;          int i, iDirection = 255, mask;
1667            VECTOR pmv[7];
         int i, iDirection, mask;  
         VECTOR currentMV, pmv[7];  
1668          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1669          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
1670          SearchData Data;          Data->iFcode = iFcode;
1671            Data->qpel_precision = 0;
1672            Data->temp[5] = Data->temp[6] = Data->temp[7] = 256*4096; /* reset chroma-sad cache */
1673    
1674            Data->RefP[0] = pRef->y + (x + Data->iEdgedWidth*y) * 16;
1675            Data->RefP[2] = pRefH + (x + Data->iEdgedWidth*y) * 16;
1676            Data->RefP[1] = pRefV + (x + Data->iEdgedWidth*y) * 16;
1677            Data->RefP[3] = pRefHV + (x + Data->iEdgedWidth*y) * 16;
1678            Data->RefP[4] = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1679            Data->RefP[5] = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1680    
1681          Data.iMinSAD = &iMinSAD;          Data->predMV = *predMV;
1682          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
1683          Data.iEdgedWidth = iEdgedWidth;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1684          Data.currentMV = &currentMV;                                  pParam->width, pParam->height, iFcode - Data->qpel, 0, 0);
1685          Data.iMinSAD = &iMinSAD;  
1686          Data.Ref = pRef + (x + y * iEdgedWidth) * 16;          pmv[0] = Data->predMV;
1687          Data.RefH = pRefH + (x + y * iEdgedWidth) * 16;          if (Data->qpel) { pmv[0].x /= 2; pmv[0].y /= 2; }
         Data.RefV = pRefV + (x + y * iEdgedWidth) * 16;  
         Data.RefHV = pRefHV + (x + y * iEdgedWidth) * 16;  
   
         Data.iQuant = iQuant;  
         Data.iFcode = iFcode;  
         Data.predMV = *predMV;  
   
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,  
                                 pParam->width, pParam->height, iFcode);  
   
         if (!(MotionFlags & PMV_HALFPEL16)) {  
                 Data.min_dx = EVEN(Data.min_dx);  
                 Data.max_dx = EVEN(Data.max_dx);  
                 Data.min_dy = EVEN(Data.min_dy);  
                 Data.max_dy = EVEN(Data.max_dy); } // no-halpel and b-frames. do we need it?  
   
   
         pmv[0] = Data.predMV;  
         PreparePredictionsBF(pmv, x, y, pParam->mb_width,  
                                         pMB, mode_current);  
1688    
1689          currentMV.x = currentMV.y = 0;          PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
1690    
1691            Data->currentMV->x = Data->currentMV->y = 0;
1692          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1693    
1694  // main loop. checking all predictions          /* main loop. checking all predictions */
1695          for (i = 0; i < 8; i++) {          for (i = 0; i < 7; i++) {
1696                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1697                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1698          }          }
1699    
1700          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & XVID_ME_USESQUARES16) MainSearchPtr = SquareSearch;
1701                  MainSearchPtr = SquareSearch;          else if (MotionFlags & XVID_ME_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
         else if (MotionFlags & PMV_ADVANCEDDIAMOND16)  
                 MainSearchPtr = AdvDiamondSearch;  
1702                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1703    
1704          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          MainSearchPtr(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1705    
1706            SubpelRefine(Data);
1707    
1708          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (Data->qpel && *Data->iMinSAD < *best_sad + 300) {
1709                    Data->currentQMV->x = 2*Data->currentMV->x;
1710                    Data->currentQMV->y = 2*Data->currentMV->y;
1711                    Data->qpel_precision = 1;
1712                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1713                                            pParam->width, pParam->height, iFcode, 1, 0);
1714                    SubpelRefine(Data);
1715            }
1716    
1717  // three bits are needed to code backward mode. four for forward          /* three bits are needed to code backward mode. four for forward */
 // we treat the bits just like they were vector's  
         if (mode_current == MODE_FORWARD) iMinSAD +=  4 * lambda_vec16[iQuant];  
         else iMinSAD +=  3 * lambda_vec16[iQuant];  
1718    
1719            if (mode_current == MODE_FORWARD) *Data->iMinSAD += 4 * Data->lambda16;
1720            else *Data->iMinSAD += 3 * Data->lambda16;
1721    
1722          if (iMinSAD < *best_sad) {          if (*Data->iMinSAD < *best_sad) {
1723                  *best_sad = iMinSAD;                  *best_sad = *Data->iMinSAD;
1724                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1725                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  if (Data->qpel) {
1726                  pMB->pmvs[0].y = currentMV.y - predMV->y;                          pMB->pmvs[0].x = Data->currentQMV->x - predMV->x;
1727                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                          pMB->pmvs[0].y = Data->currentQMV->y - predMV->y;
1728                  else pMB->b_mvs[0] = currentMV;                          if (mode_current == MODE_FORWARD)
1729                                    pMB->qmvs[0] = *Data->currentQMV;
1730                            else
1731                                    pMB->b_qmvs[0] = *Data->currentQMV;
1732                    } else {
1733                            pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1734                            pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1735                    }
1736                    if (mode_current == MODE_FORWARD) pMB->mvs[0] = *Data->currentMV;
1737                    else pMB->b_mvs[0] = *Data->currentMV;
1738          }          }
1739    
1740            if (mode_current == MODE_FORWARD) *(Data->currentMV+2) = *Data->currentMV;
1741            else *(Data->currentMV+1) = *Data->currentMV; /* we store currmv for interpolate search */
1742  }  }
1743    
1744  static int32_t  static void
1745    SkipDecisionB(const IMAGE * const pCur,
1746                                    const IMAGE * const f_Ref,
1747                                    const IMAGE * const b_Ref,
1748                                    MACROBLOCK * const pMB,
1749                                    const uint32_t x, const uint32_t y,
1750                                    const SearchData * const Data)
1751    {
1752            int dx = 0, dy = 0, b_dx = 0, b_dy = 0;
1753            int32_t sum;
1754            const int div = 1 + Data->qpel;
1755            int k;
1756            const uint32_t stride = Data->iEdgedWidth/2;
1757            /* this is not full chroma compensation, only it's fullpel approximation. should work though */
1758    
1759            for (k = 0; k < 4; k++) {
1760                    dy += Data->directmvF[k].y / div;
1761                    dx += Data->directmvF[k].x / div;
1762                    b_dy += Data->directmvB[k].y / div;
1763                    b_dx += Data->directmvB[k].x / div;
1764            }
1765    
1766            dy = (dy >> 3) + roundtab_76[dy & 0xf];
1767            dx = (dx >> 3) + roundtab_76[dx & 0xf];
1768            b_dy = (b_dy >> 3) + roundtab_76[b_dy & 0xf];
1769            b_dx = (b_dx >> 3) + roundtab_76[b_dx & 0xf];
1770    
1771            sum = sad8bi(pCur->u + 8 * x + 8 * y * stride,
1772                                            f_Ref->u + (y*8 + dy/2) * stride + x*8 + dx/2,
1773                                            b_Ref->u + (y*8 + b_dy/2) * stride + x*8 + b_dx/2,
1774                                            stride);
1775    
1776            if (sum >= MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) return; /* no skip */
1777    
1778            sum += sad8bi(pCur->v + 8*x + 8 * y * stride,
1779                                            f_Ref->v + (y*8 + dy/2) * stride + x*8 + dx/2,
1780                                            b_Ref->v + (y*8 + b_dy/2) * stride + x*8 + b_dx/2,
1781                                            stride);
1782    
1783            if (sum < MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) {
1784                    pMB->mode = MODE_DIRECT_NONE_MV; /* skipped */
1785                    for (k = 0; k < 4; k++) {
1786                            pMB->qmvs[k] = pMB->mvs[k];
1787                            pMB->b_qmvs[k] = pMB->b_mvs[k];
1788                    }
1789            }
1790    }
1791    
1792    static __inline uint32_t
1793  SearchDirect(const IMAGE * const f_Ref,  SearchDirect(const IMAGE * const f_Ref,
1794                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1795                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
# Line 1041  Line 1801 
1801                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1802                                  const int x, const int y,                                  const int x, const int y,
1803                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1804                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1805                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1806                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1807                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1808                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1809                                    SearchData * const Data)
1810    
1811  {  {
1812          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
1813          int32_t iMinSAD = 266*4096, skip_sad;          int k = (x + Data->iEdgedWidth*y) * 16;
         int k;  
         VECTOR currentMV;  
1814          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
         SearchData Data;  
1815    
1816          Data.iMinSAD = &iMinSAD;          *Data->iMinSAD = 256*4096;
1817          Data.Cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;          Data->RefP[0] = f_Ref->y + k;
1818          Data.iEdgedWidth = iEdgedWidth;          Data->RefP[2] = f_RefH + k;
1819          Data.currentMV = &currentMV;          Data->RefP[1] = f_RefV + k;
1820          Data.iQuant = iQuant;          Data->RefP[3] = f_RefHV + k;
1821          Data.referencemv = b_mb->mvs;          Data->b_RefP[0] = b_Ref->y + k;
1822            Data->b_RefP[2] = b_RefH + k;
1823          Data.Ref= f_Ref->y + (x + iEdgedWidth*y) * 16;          Data->b_RefP[1] = b_RefV + k;
1824          Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;          Data->b_RefP[3] = b_RefHV + k;
1825          Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;          Data->RefP[4] = f_Ref->u + (x + (Data->iEdgedWidth/2) * y) * 8;
1826          Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;          Data->RefP[5] = f_Ref->v + (x + (Data->iEdgedWidth/2) * y) * 8;
1827          Data.bRef = b_Ref->y + (x + iEdgedWidth*y) * 16;          Data->b_RefP[4] = b_Ref->u + (x + (Data->iEdgedWidth/2) * y) * 8;
1828          Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;          Data->b_RefP[5] = b_Ref->v + (x + (Data->iEdgedWidth/2) * y) * 8;
1829          Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;  
1830          Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;          k = Data->qpel ? 4 : 2;
1831  /*          Data->max_dx = k * (pParam->width - x * 16);
1832  //What we do here is a complicated version of CheckCandidateDirect(0,0);          Data->max_dy = k * (pParam->height - y * 16);
1833  get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16, pParam->width, pParam->height, 19);          Data->min_dx = -k * (16 + x * 16);
1834            Data->min_dy = -k * (16 + y * 16);
1835    
1836  */          Data->referencemv = Data->qpel ? b_mb->qmvs : b_mb->mvs;
1837          Data.max_dx = 2 * pParam->width - 2 * (x) * 16;          Data->qpel_precision = 0;
         Data.max_dy = 2 * pParam->height - 2 * (y) * 16;  
         Data.min_dx = -(2 * 16 + 2 * (x) * 16);  
         Data.min_dy = -(2 * 16 + 2 * (y) * 16);  
1838    
1839          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1840                  pMB->mvs[k].x = Data.directmvF[k].x = ((TRB * Data.referencemv[k].x) / TRD);                  pMB->mvs[k].x = Data->directmvF[k].x = ((TRB * Data->referencemv[k].x) / TRD);
1841                  pMB->b_mvs[k].x = Data.directmvB[k].x = ((TRB - TRD) * Data.referencemv[k].x) / TRD;                  pMB->b_mvs[k].x = Data->directmvB[k].x = ((TRB - TRD) * Data->referencemv[k].x) / TRD;
1842                  pMB->mvs[k].y = Data.directmvF[k].y = ((TRB * Data.referencemv[k].y) / TRD);                  pMB->mvs[k].y = Data->directmvF[k].y = ((TRB * Data->referencemv[k].y) / TRD);
1843                  pMB->b_mvs[k].y = Data.directmvB[k].y = ((TRB - TRD) * Data.referencemv[k].y) / TRD;                  pMB->b_mvs[k].y = Data->directmvB[k].y = ((TRB - TRD) * Data->referencemv[k].y) / TRD;
1844    
1845                  if (( pMB->mvs[k].x > Data.max_dx ) || ( pMB->mvs[k].x < Data.min_dx )                  if ( (pMB->b_mvs[k].x > Data->max_dx) | (pMB->b_mvs[k].x < Data->min_dx)
1846                          || ( pMB->mvs[k].y > Data.max_dy ) || ( pMB->mvs[k].y < Data.min_dy )                          | (pMB->b_mvs[k].y > Data->max_dy) | (pMB->b_mvs[k].y < Data->min_dy) ) {
                         || ( pMB->b_mvs[k].x > Data.max_dx ) || ( pMB->b_mvs[k].x < Data.min_dx )  
                         || ( pMB->b_mvs[k].y > Data.max_dy ) || ( pMB->b_mvs[k].y < Data.min_dy )) {  
1847    
1848                          *best_sad = 256*4096; // in that case, we won't use direct mode                          *best_sad = 256*4096; /* in that case, we won't use direct mode */
1849                          pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"                          pMB->mode = MODE_DIRECT; /* just to make sure it doesn't say "MODE_DIRECT_NONE_MV" */
1850                          pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;                          pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;
1851                          return 0;                          return 256*4096;
1852                  }                  }
1853                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1854                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1855                          pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];                          pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];
1856                          Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1857                          Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1858                          break;                          break;
1859                  }                  }
1860          }          }
1861    
1862          if (b_mb->mode == MODE_INTER4V)          CheckCandidate = b_mb->mode == MODE_INTER4V ? CheckCandidateDirect : CheckCandidateDirectno4v;
                 CheckCandidate = CheckCandidateDirect;  
         else CheckCandidate = CheckCandidateDirectno4v;  
   
         (*CheckCandidate)(0, 0, 255, &k, &Data);  
1863    
1864  // skip decision          CheckCandidate(0, 0, 255, &k, Data);
         if (iMinSAD - 2 * lambda_vec16[iQuant] < (int32_t)iQuant * SKIP_THRESH_B) {  
                 //checking chroma. everything copied from MC  
                 //this is not full chroma compensation, only it's fullpel approximation. should work though  
                 int sum, dx, dy, b_dx, b_dy;  
1865    
1866                  sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;          /* initial (fast) skip decision */
1867                  dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));          if (*Data->iMinSAD < pMB->quant * INITIAL_SKIP_THRESH * (Data->chroma?3:2)) {
1868                    /* possible skip */
1869                  sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;                  if (Data->chroma) {
                 dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));  
   
                 sum = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;  
                 b_dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));  
   
                 sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;  
                 b_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));  
   
                 sum = sad8bi(pCur->u + 8*x + 8*y*(iEdgedWidth/2),  
                                         f_Ref->u + (y*8 + dy/2) * (iEdgedWidth/2) + x*8 + dx/2,  
                                         b_Ref->u + (y*8 + b_dy/2) * (iEdgedWidth/2) + x*8 + b_dx/2,  
                                         iEdgedWidth/2);  
                 sum += sad8bi(pCur->v + 8*x + 8*y*(iEdgedWidth/2),  
                                         f_Ref->v + (y*8 + dy/2) * (iEdgedWidth/2) + x*8 + dx/2,  
                                         b_Ref->v + (y*8 + b_dy/2) * (iEdgedWidth/2) + x*8 + b_dx/2,  
                                         iEdgedWidth/2);  
   
                 if ((uint32_t) sum < MAX_CHROMA_SAD_FOR_SKIP * Data.iQuant) {  
1870                          pMB->mode = MODE_DIRECT_NONE_MV;                          pMB->mode = MODE_DIRECT_NONE_MV;
1871                          return iMinSAD;                          return *Data->iMinSAD; /* skip. */
1872                    } else {
1873                            SkipDecisionB(pCur, f_Ref, b_Ref, pMB, x, y, Data);
1874                            if (pMB->mode == MODE_DIRECT_NONE_MV) return *Data->iMinSAD; /* skip. */
1875                  }                  }
1876          }          }
1877    
1878          skip_sad = iMinSAD;          *Data->iMinSAD += Data->lambda16;
1879            skip_sad = *Data->iMinSAD;
1880    
1881  //  DIRECT MODE DELTA VECTOR SEARCH.          /*
1882  //      This has to be made more effective, but at the moment I'm happy it's running at all           * DIRECT MODE DELTA VECTOR SEARCH.
1883             * This has to be made more effective, but at the moment I'm happy it's running at all
1884             */
1885    
1886          if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;          if (MotionFlags & XVID_ME_USESQUARES16) MainSearchPtr = SquareSearch;
1887                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & XVID_ME_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1888                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1889    
1890          (*MainSearchPtr)(0, 0, &Data, 255);          MainSearchPtr(0, 0, Data, 255);
1891    
1892          HalfpelRefine(&Data);          SubpelRefine(Data);
1893    
1894          iMinSAD +=  1 * lambda_vec16[iQuant]; // one bit is needed to code direct mode. we treat this bit just like it was vector's          *best_sad = *Data->iMinSAD;
         *best_sad = iMinSAD;  
1895    
1896          if (b_mb->mode == MODE_INTER4V)          if (Data->qpel || b_mb->mode == MODE_INTER4V) pMB->mode = MODE_DIRECT;
1897                  pMB->mode = MODE_DIRECT;          else pMB->mode = MODE_DIRECT_NO4V; /* for faster compensation */
         else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation  
1898    
1899          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1900    
1901          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1902                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1903                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = (     (Data->currentMV->x == 0)
1904                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1905                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          :pMB->mvs[k].x - Data->referencemv[k].x);
1906                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1907                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1908                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1909                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1910                    if (Data->qpel) {
1911                            pMB->qmvs[k].x = pMB->mvs[k].x; pMB->mvs[k].x /= 2;
1912                            pMB->b_qmvs[k].x = pMB->b_mvs[k].x; pMB->b_mvs[k].x /= 2;
1913                            pMB->qmvs[k].y = pMB->mvs[k].y; pMB->mvs[k].y /= 2;
1914                            pMB->b_qmvs[k].y = pMB->b_mvs[k].y; pMB->b_mvs[k].y /= 2;
1915                    }
1916    
1917                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1918                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1919                          pMB->b_mvs[3] = pMB->b_mvs[2] = pMB->b_mvs[1] = pMB->b_mvs[0];                          pMB->b_mvs[3] = pMB->b_mvs[2] = pMB->b_mvs[1] = pMB->b_mvs[0];
1920                            pMB->qmvs[3] = pMB->qmvs[2] = pMB->qmvs[1] = pMB->qmvs[0];
1921                            pMB->b_qmvs[3] = pMB->b_qmvs[2] = pMB->b_qmvs[1] = pMB->b_qmvs[0];
1922                          break;                          break;
1923                  }                  }
1924          }          }
1925          return 0;//skip_sad;          return skip_sad;
1926  }  }
1927    
1928  static __inline void  static void
1929  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const IMAGE * const f_Ref,
1930                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1931                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
1932                                  const uint8_t * const f_RefHV,                                  const uint8_t * const f_RefHV,
1933                                  const uint8_t * const b_Ref,                                  const IMAGE * const b_Ref,
1934                                  const uint8_t * const b_RefH,                                  const uint8_t * const b_RefH,
1935                                  const uint8_t * const b_RefV,                                  const uint8_t * const b_RefV,
1936                                  const uint8_t * const b_RefHV,                                  const uint8_t * const b_RefHV,
# Line 1199  Line 1939 
1939                                  const uint32_t fcode,                                  const uint32_t fcode,
1940                                  const uint32_t bcode,                                  const uint32_t bcode,
1941                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1942                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1943                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1944                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1945                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1946                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1947                                    SearchData * const fData)
1948    
1949  {  {
 /* Interpolated MC motion vector search, this is tedious and more complicated because there are  
    two values for everything, always one for backward and one for forward ME. Still, we don't gain  
    much from this search, maybe it should simply be skipped and simply current i_sad16 value used  
    as "optimal". */  
   
         const int32_t iEdgedWidth = pParam->edged_width;  
1950    
1951          int iDirection, i, j;          int iDirection, i, j;
1952          int32_t iMinSAD = 256*4096;          SearchData bData;
         VECTOR currentMV[3];  
         SearchData fData, bData;  
1953    
1954          fData.iMinSAD = bData.iMinSAD = &iMinSAD;          fData->qpel_precision = 0;
1955            memcpy(&bData, fData, sizeof(SearchData)); /* quick copy of common data */
1956            *fData->iMinSAD = 4096*256;
1957            bData.currentMV++; bData.currentQMV++;
1958            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1959    
1960            i = (x + y * fData->iEdgedWidth) * 16;
1961    
1962            bData.b_RefP[0] = fData->RefP[0] = f_Ref->y + i;
1963            bData.b_RefP[2] = fData->RefP[2] = f_RefH + i;
1964            bData.b_RefP[1] = fData->RefP[1] = f_RefV + i;
1965            bData.b_RefP[3] = fData->RefP[3] = f_RefHV + i;
1966            bData.RefP[0] = fData->b_RefP[0] = b_Ref->y + i;
1967            bData.RefP[2] = fData->b_RefP[2] = b_RefH + i;
1968            bData.RefP[1] = fData->b_RefP[1] = b_RefV + i;
1969            bData.RefP[3] = fData->b_RefP[3] = b_RefHV + i;
1970            bData.b_RefP[4] = fData->RefP[4] = f_Ref->u + (x + (fData->iEdgedWidth/2) * y) * 8;
1971            bData.b_RefP[5] = fData->RefP[5] = f_Ref->v + (x + (fData->iEdgedWidth/2) * y) * 8;
1972            bData.RefP[4] = fData->b_RefP[4] = b_Ref->u + (x + (fData->iEdgedWidth/2) * y) * 8;
1973            bData.RefP[5] = fData->b_RefP[5] = b_Ref->v + (x + (fData->iEdgedWidth/2) * y) * 8;
1974    
1975            bData.bpredMV = fData->predMV = *f_predMV;
1976            fData->bpredMV = bData.predMV = *b_predMV;
1977            fData->currentMV[0] = fData->currentMV[2];
1978    
1979            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);
1980            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);
1981    
1982            if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1983            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dx;
1984            if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dy;
1985            if (fData->currentMV[0].y < fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1986    
1987            if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1988            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dx;
1989            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dy;
1990            if (fData->currentMV[1].y < bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1991    
1992          fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
         fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;  
         fData.currentMV = currentMV; bData.currentMV = currentMV + 1;  
         fData.iQuant = bData.iQuant = iQuant;  
         fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;  
   
         bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  
         bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;  
         bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;  
         bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;  
         bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;  
         bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;  
         bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;  
         bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;  
   
         bData.bpredMV = fData.predMV = *f_predMV;  
         fData.bpredMV = bData.predMV = *b_predMV;  
   
         currentMV[0] = pMB->mvs[0];  
         currentMV[1] = pMB->b_mvs[0];  
         get_range(&fData.min_dx, &fData.max_dx, &fData.min_dy, &fData.max_dy, x, y, 16, pParam->width, pParam->height, fcode);  
         get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode);  
   
         if (currentMV[0].x > fData.max_dx) currentMV[0].x = fData.max_dx;  
         if (currentMV[0].x < fData.min_dx) currentMV[0].x = fData.min_dy;  
         if (currentMV[0].y > fData.max_dy) currentMV[0].y = fData.max_dx;  
         if (currentMV[0].y > fData.min_dy) currentMV[0].y = fData.min_dy;  
   
         if (currentMV[1].x > bData.max_dx) currentMV[1].x = bData.max_dx;  
         if (currentMV[1].x < bData.min_dx) currentMV[1].x = bData.min_dy;  
         if (currentMV[1].y > bData.max_dy) currentMV[1].y = bData.max_dx;  
         if (currentMV[1].y > bData.min_dy) currentMV[1].y = bData.min_dy;  
   
         CheckCandidateInt(currentMV[0].x, currentMV[0].y, 255, &iDirection, &fData);  
   
 //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  
1993    
1994            /* diamond */
1995          do {          do {
1996                  iDirection = 255;                  iDirection = 255;
1997                  // forward MV moves                  /* forward MV moves */
1998                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
   
                 CheckCandidateInt(i + 1, j, 0, &iDirection, &fData);  
                 CheckCandidateInt(i, j + 1, 0, &iDirection, &fData);  
                 CheckCandidateInt(i - 1, j, 0, &iDirection, &fData);  
                 CheckCandidateInt(i, j - 1, 0, &iDirection, &fData);  
   
                 // backward MV moves  
                 i = currentMV[1].x; j = currentMV[1].y;  
                 currentMV[2] = currentMV[0];  
1999    
2000                    CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
2001                    CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
2002                    CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
2003                    CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
2004    
2005                    /* backward MV moves */
2006                    i = fData->currentMV[1].x; j = fData->currentMV[1].y;
2007                    fData->currentMV[2] = fData->currentMV[0];
2008                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
2009                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
2010                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
# Line 1279  Line 2012 
2012    
2013          } while (!(iDirection));          } while (!(iDirection));
2014    
2015  // two bits are needed to code interpolate mode. we treat the bits just like they were vector's          /* qpel refinement */
2016          iMinSAD +=  2 * lambda_vec16[iQuant];          if (fData->qpel) {
2017          if (iMinSAD < *best_sad) {                  if (*fData->iMinSAD > *best_sad + 500) return;
2018                  *best_sad = iMinSAD;                  CheckCandidate = CheckCandidateInt;
2019                  pMB->mvs[0] = currentMV[0];                  fData->qpel_precision = bData.qpel_precision = 1;
2020                  pMB->b_mvs[0] = currentMV[1];                  get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, 1, 0);
2021                    get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, 1, 0);
2022                    fData->currentQMV[2].x = fData->currentQMV[0].x = 2 * fData->currentMV[0].x;
2023                    fData->currentQMV[2].y = fData->currentQMV[0].y = 2 * fData->currentMV[0].y;
2024                    fData->currentQMV[1].x = 2 * fData->currentMV[1].x;
2025                    fData->currentQMV[1].y = 2 * fData->currentMV[1].y;
2026                    SubpelRefine(fData);
2027                    if (*fData->iMinSAD > *best_sad + 300) return;
2028                    fData->currentQMV[2] = fData->currentQMV[0];
2029                    SubpelRefine(&bData);
2030            }
2031    
2032            *fData->iMinSAD += (2+3) * fData->lambda16; /* two bits are needed to code interpolate mode. */
2033    
2034            if (*fData->iMinSAD < *best_sad) {
2035                    *best_sad = *fData->iMinSAD;
2036                    pMB->mvs[0] = fData->currentMV[0];
2037                    pMB->b_mvs[0] = fData->currentMV[1];
2038                  pMB->mode = MODE_INTERPOLATE;                  pMB->mode = MODE_INTERPOLATE;
2039                    if (fData->qpel) {
2040                            pMB->qmvs[0] = fData->currentQMV[0];
2041                            pMB->b_qmvs[0] = fData->currentQMV[1];
2042                            pMB->pmvs[1].x = pMB->qmvs[0].x - f_predMV->x;
2043                            pMB->pmvs[1].y = pMB->qmvs[0].y - f_predMV->y;
2044                            pMB->pmvs[0].x = pMB->b_qmvs[0].x - b_predMV->x;
2045                            pMB->pmvs[0].y = pMB->b_qmvs[0].y - b_predMV->y;
2046                    } else {
2047                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;
2048                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;
2049                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;
2050                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;
2051          }          }
2052  }  }
2053    }
2054    
2055  void  void
2056  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
2057                                           FRAMEINFO * const frame,                                           FRAMEINFO * const frame,
2058                                           const int32_t time_bp,                                           const int32_t time_bp,
2059                                           const int32_t time_pp,                                           const int32_t time_pp,
2060                                           // forward (past) reference                                           /* forward (past) reference */
2061                                           const MACROBLOCK * const f_mbs,                                           const MACROBLOCK * const f_mbs,
2062                                           const IMAGE * const f_ref,                                           const IMAGE * const f_ref,
2063                                           const IMAGE * const f_refH,                                           const IMAGE * const f_refH,
2064                                           const IMAGE * const f_refV,                                           const IMAGE * const f_refV,
2065                                           const IMAGE * const f_refHV,                                           const IMAGE * const f_refHV,
2066                                           // backward (future) reference                                           /* backward (future) reference */
2067                                           const MACROBLOCK * const b_mbs,                                           const FRAMEINFO * const b_reference,
2068                                           const IMAGE * const b_ref,                                           const IMAGE * const b_ref,
2069                                           const IMAGE * const b_refH,                                           const IMAGE * const b_refH,
2070                                           const IMAGE * const b_refV,                                           const IMAGE * const b_refV,
2071                                           const IMAGE * const b_refHV)                                           const IMAGE * const b_refHV)
2072  {  {
2073          uint32_t i, j;          uint32_t i, j;
2074          int32_t best_sad, skip_sad;          int32_t best_sad;
2075            uint32_t skip_sad;
2076          int f_count = 0, b_count = 0, i_count = 0, d_count = 0, n_count = 0;          int f_count = 0, b_count = 0, i_count = 0, d_count = 0, n_count = 0;
2077          static const VECTOR zeroMV={0,0};          const MACROBLOCK * const b_mbs = b_reference->mbs;
2078    
2079          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
2080    
2081          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
2082          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
2083    
2084          // note: i==horizontal, j==vertical          /* some pre-inintialized data for the rest of the search */
2085    
2086            SearchData Data;
2087            int32_t iMinSAD;
2088            VECTOR currentMV[3];
2089            VECTOR currentQMV[3];
2090            int32_t temp[8];
2091            memset(&Data, 0, sizeof(SearchData));
2092            Data.iEdgedWidth = pParam->edged_width;
2093            Data.currentMV = currentMV; Data.currentQMV = currentQMV;
2094            Data.iMinSAD = &iMinSAD;
2095            Data.lambda16 = lambda_vec16[frame->quant];
2096            Data.qpel = pParam->vol_flags & XVID_VOL_QUARTERPEL ? 1 : 0;
2097            Data.rounding = 0;
2098            Data.chroma = frame->motion_flags & XVID_ME_CHROMA_BVOP;
2099            Data.temp = temp;
2100    
2101            Data.RefQ = f_refV->u; /* a good place, also used in MC (for similar purpose) */
2102    
2103            /* note: i==horizontal, j==vertical */
2104          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
2105    
2106                  f_predMV = b_predMV = zeroMV;   /* prediction is reset at left boundary */                  f_predMV = b_predMV = zeroMV;   /* prediction is reset at left boundary */
# Line 1332  Line 2109 
2109                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;
2110                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;
2111    
2112  /* special case, if collocated block is SKIPed: encoding is forward (0,0), cpb=0 without further ado */  /* special case, if collocated block is SKIPed in P-VOP: encoding is forward (0,0), cpb=0 without further ado */
2113                            if (b_reference->coding_type != S_VOP)
2114                          if (b_mb->mode == MODE_NOT_CODED) {                          if (b_mb->mode == MODE_NOT_CODED) {
2115                                  pMB->mode = MODE_NOT_CODED;                                  pMB->mode = MODE_NOT_CODED;
2116                                  continue;                                  continue;
2117                          }                          }
2118    
2119                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
2120                            Data.CurU = frame->image.u + (j * Data.iEdgedWidth/2 + i) * 8;
2121                            Data.CurV = frame->image.v + (j * Data.iEdgedWidth/2 + i) * 8;
2122                            pMB->quant = frame->quant;
2123    
2124  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
2125          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
   
2126                          skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,                          skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
2127                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,
2128                                                                          &frame->image,                                                                          &frame->image,
2129                                                                          i, j,                                                                          i, j,
2130                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
2131                                                                          TRB, TRD,                                                                          TRB, TRD,
2132                                                                          pParam,                                                                          pParam,
2133                                                                          pMB, b_mb,                                                                          pMB, b_mb,
2134                                                                          &best_sad);                                                                          &best_sad,
2135                                                                            &Data);
2136    
2137                          if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                          if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
2138    
2139  //                      best_sad = 256*4096; //uncomment to disable Directsearch.                          /* forward search */
2140  //      To disable any other mode, just comment the function call                          SearchBF(f_ref, f_refH->y, f_refV->y, f_refHV->y,
   
                         // forward search  
                         SearchBF(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,  
2141                                                  &frame->image, i, j,                                                  &frame->image, i, j,
2142                                                  frame->motion_flags,                                                  frame->motion_flags,
2143                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
2144                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
2145                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
2146    
2147                          // backward search                          /* backward search */
2148                          SearchBF(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                          SearchBF(b_ref, b_refH->y, b_refV->y, b_refHV->y,
2149                                                  &frame->image, i, j,                                                  &frame->image, i, j,
2150                                                  frame->motion_flags,                                                  frame->motion_flags,
2151                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
2152                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
2153                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
2154    
2155                          // interpolate search comes last, because it uses data from forward and backward as prediction                          /* interpolate search comes last, because it uses data from forward and backward as prediction */
2156                            SearchInterpolate(f_ref, f_refH->y, f_refV->y, f_refHV->y,
2157                          SearchInterpolate(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                                  b_ref, b_refH->y, b_refV->y, b_refHV->y,
                                                 b_ref->y, b_refH->y, b_refV->y, b_refHV->y,  
2158                                                  &frame->image,                                                  &frame->image,
2159                                                  i, j,                                                  i, j,
2160                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
2161                                                  frame->motion_flags,                                                  frame->motion_flags,
2162                                                  frame->quant, pParam,                                                  pParam,
2163                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
2164                                                  pMB, &best_sad);                                                  pMB, &best_sad,
2165                                                    &Data);
2166    
2167                            /* final skip decision */
2168                            if ( (skip_sad < frame->quant * MAX_SAD00_FOR_SKIP * 2)
2169                                            && ((100*best_sad)/(skip_sad+1) > FINAL_SKIP_THRESH) )
2170                                    SkipDecisionB(&frame->image, f_ref, b_ref, pMB, i, j, &Data);
2171    
2172                          switch (pMB->mode) {                          switch (pMB->mode) {
2173                                  case MODE_FORWARD:                                  case MODE_FORWARD:
2174                                          f_count++;                                          f_count++;
2175                                          f_predMV = pMB->mvs[0];                                          f_predMV = Data.qpel ? pMB->qmvs[0] : pMB->mvs[0];
2176                                          break;                                          break;
2177                                  case MODE_BACKWARD:                                  case MODE_BACKWARD:
2178                                          b_count++;                                          b_count++;
2179                                          b_predMV = pMB->b_mvs[0];                                          b_predMV = Data.qpel ? pMB->b_qmvs[0] : pMB->b_mvs[0];
2180                                          break;                                          break;
2181                                  case MODE_INTERPOLATE:                                  case MODE_INTERPOLATE:
2182                                          i_count++;                                          i_count++;
2183                                          f_predMV = pMB->mvs[0];                                          f_predMV = Data.qpel ? pMB->qmvs[0] : pMB->mvs[0];
2184                                          b_predMV = pMB->b_mvs[0];                                          b_predMV = Data.qpel ? pMB->b_qmvs[0] : pMB->b_mvs[0];
2185                                          break;                                          break;
2186                                  case MODE_DIRECT:                                  case MODE_DIRECT:
2187                                  case MODE_DIRECT_NO4V:                                  case MODE_DIRECT_NO4V:
2188                                          d_count++;                                          d_count++;
                                         break;  
2189                                  default:                                  default:
2190                                          break;                                          break;
2191                          }                          }
2192                  }                  }
2193          }          }
   
 //      fprintf(debug,"B-Stat: F: %04d   B: %04d   I: %04d  D: %04d, N: %04d\n",  
 //                              f_count,b_count,i_count,d_count,n_count);  
   
2194  }  }
2195    
 /* Hinted ME starts here */  
   
2196  static __inline void  static __inline void
2197  Search8hinted(  const SearchData * const OldData,  MEanalyzeMB (   const uint8_t * const pRef,
2198                                  const int x, const int y,                                  const uint8_t * const pCur,
2199                                  const uint32_t MotionFlags,                                  const int x,
2200                                    const int y,
2201                                  const MBParam * const pParam,                                  const MBParam * const pParam,
2202                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMBs,
2203                                  const MACROBLOCK * const pMBs,                                  SearchData * const Data)
                                 const int block)  
2204  {  {
         SearchData Data;  
         MainSearchFunc *MainSearchPtr;  
2205    
2206          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          int i, mask;
2207          Data.iMinSAD = OldData->iMinSAD + 1 + block;          int quarterpel = (pParam->vol_flags & XVID_VOL_QUARTERPEL)? 1: 0;
2208          Data.currentMV = OldData->currentMV+1+block;          VECTOR pmv[3];
2209          Data.iFcode = OldData->iFcode;          MACROBLOCK * const pMB = &pMBs[x + y * pParam->mb_width];
2210          Data.iQuant = OldData->iQuant;  
2211            for (i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
2212          Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));  
2213          Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));          /* median is only used as prediction. it doesn't have to be real */
2214          Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));          if (x == 1 && y == 1) Data->predMV.x = Data->predMV.y = 0;
2215          Data.RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));          else
2216          Data.iEdgedWidth = pParam->edged_width;                  if (x == 1) /* left macroblock does not have any vector now */
2217          Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                          Data->predMV = (pMB - pParam->mb_width)->mvs[0]; /* top instead of median */
2218                    else if (y == 1) /* top macroblock doesn't have it's vector */
2219          CheckCandidate = CheckCandidate8;                          Data->predMV = (pMB - 1)->mvs[0]; /* left instead of median */
2220                            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); /* else median */
2221    
2222          if (block != 0)          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2223                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *                          pParam->width, pParam->height, Data->iFcode - quarterpel, 0, 0);
                                                                 d_mv_bits(      Data.currentMV->x - Data.predMV.x,  
                                                                                         Data.currentMV->y - Data.predMV.y,  
                                                                                         Data.iFcode);  
2224    
2225            Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
2226            Data->RefP[0] = pRef + (x + y * pParam->edged_width) * 16;
2227    
2228          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,          pmv[1].x = EVEN(pMB->mvs[0].x);
2229                                  pParam->width, pParam->height, OldData->iFcode);          pmv[1].y = EVEN(pMB->mvs[0].y);
2230            pmv[2].x = EVEN(Data->predMV.x);
2231            pmv[2].y = EVEN(Data->predMV.y);
2232            pmv[0].x = pmv[0].y = 0;
2233    
2234          if (pMB->mode == MODE_INTER4V) {          CheckCandidate32I(0, 0, 255, &i, Data);
                 int dummy;  
                 CheckCandidate8(pMB->mvs[block].x, pMB->mvs[block].y, 0, &dummy, &Data); }  
2235    
2236          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;          if (*Data->iMinSAD > 4 * MAX_SAD00_FOR_SKIP) {
                 else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;  
                         else MainSearchPtr = DiamondSearch;  
2237    
2238          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);                  if (!(mask = make_mask(pmv, 1)))
2239                            CheckCandidate32I(pmv[1].x, pmv[1].y, mask, &i, Data);
2240                    if (!(mask = make_mask(pmv, 2)))
2241                            CheckCandidate32I(pmv[2].x, pmv[2].y, mask, &i, Data);
2242    
2243          if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                  if (*Data->iMinSAD > 4 * MAX_SAD00_FOR_SKIP) /* diamond only if needed */
2244                            DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
2245            }
2246    
2247          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;          for (i = 0; i < 4; i++) {
2248          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;                  MACROBLOCK * MB = &pMBs[x + (i&1) + (y+(i>>1)) * pParam->mb_width];
2249          pMB->mvs[block] = *(Data.currentMV);                  MB->mvs[0] = MB->mvs[1] = MB->mvs[2] = MB->mvs[3] = Data->currentMV[i];
2250          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                  MB->mode = MODE_INTER;
2251                    MB->sad16 = Data->iMinSAD[i+1];
2252            }
2253  }  }
2254    
2255    #define INTRA_THRESH    2200
2256    #define INTER_THRESH    50
2257    #define INTRA_THRESH2   95
2258    
2259  static void  int
2260  SearchPhinted ( const uint8_t * const pRef,  MEanalysis(     const IMAGE * const pRef,
2261                                  const uint8_t * const pRefH,                          const FRAMEINFO * const Current,
                                 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,  
2262                                  const MBParam * const pParam,                                  const MBParam * const pParam,
2263                                  const MACROBLOCK * const pMBs,                          const int maxIntra, //maximum number if non-I frames
2264                                  int inter4v,                          const int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame
2265                                  MACROBLOCK * const pMB)                          const int bCount, // number of B frames in a row
2266                            const int b_thresh)
2267  {  {
2268            uint32_t x, y, intra = 0;
2269            int sSAD = 0;
2270            MACROBLOCK * const pMBs = Current->mbs;
2271            const IMAGE * const pCurrent = &Current->image;
2272            int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH + b_thresh;
2273            int blocks = 0;
2274            int complexity = 0;
2275    
2276          const int32_t iEdgedWidth = pParam->edged_width;          int32_t iMinSAD[5], temp[5];
   
         int i;  
2277          VECTOR currentMV[5];          VECTOR currentMV[5];
         int32_t iMinSAD[5];  
         int32_t temp[5];  
         MainSearchFunc * MainSearchPtr;  
2278          SearchData Data;          SearchData Data;
2279            Data.iEdgedWidth = pParam->edged_width;
         Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);  
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,  
                                 pParam->width, pParam->height, iFcode);  
   
         Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
         Data.iEdgedWidth = iEdgedWidth;  
2280          Data.currentMV = currentMV;          Data.currentMV = currentMV;
2281          Data.iMinSAD = iMinSAD;          Data.iMinSAD = iMinSAD;
2282          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data.iFcode = Current->fcode;
         Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;  
         Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;  
         Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;  
2283          Data.temp = temp;          Data.temp = temp;
2284          Data.iQuant = iQuant;          CheckCandidate = CheckCandidate32I;
         Data.iFcode = iFcode;  
2285    
2286          if (!(MotionFlags & PMV_HALFPEL16)) {          if (intraCount != 0) {
2287                  Data.min_dx = EVEN(Data.min_dx);                  if (intraCount < 10) // we're right after an I frame
2288                  Data.max_dx = EVEN(Data.max_dx);                          IntraThresh += 15* (intraCount - 10) * (intraCount - 10);
2289                  Data.min_dy = EVEN(Data.min_dy);                  else
2290                  Data.max_dy = EVEN(Data.max_dy);                          if ( 5*(maxIntra - intraCount) < maxIntra) // we're close to maximum. 2 sec when max is 10 sec
2291                                    IntraThresh -= (IntraThresh * (maxIntra - 8*(maxIntra - intraCount)))/maxIntra;
2292          }          }
2293    
2294          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;          InterThresh -= 12 * bCount;
2295            if (InterThresh < 15 + b_thresh) InterThresh = 15 + b_thresh;
2296    
2297          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (sadInit) (*sadInit) ();
2298    
2299          if (inter4v)          for (y = 1; y < pParam->mb_height-1; y += 2) {
2300                  CheckCandidate = CheckCandidate16;                  for (x = 1; x < pParam->mb_width-1; x += 2) {
2301          else CheckCandidate = CheckCandidate16no4v;                          int i;
2302                            blocks += 10;
2303    
2304                            if (bCount == 0) pMBs[x + y * pParam->mb_width].mvs[0] = zeroMV;
2305                            else { //extrapolation of the vector found for last frame
2306                                    pMBs[x + y * pParam->mb_width].mvs[0].x =
2307                                            (pMBs[x + y * pParam->mb_width].mvs[0].x * (bCount+1) ) / bCount;
2308                                    pMBs[x + y * pParam->mb_width].mvs[0].y =
2309                                            (pMBs[x + y * pParam->mb_width].mvs[0].y * (bCount+1) ) / bCount;
2310                            }
2311    
2312                            MEanalyzeMB(pRef->y, pCurrent->y, x, y, pParam, pMBs, &Data);
2313    
2314                            for (i = 0; i < 4; i++) {
2315                                    int dev;
2316                                    MACROBLOCK *pMB = &pMBs[x+(i&1) + (y+(i>>1)) * pParam->mb_width];
2317                                    dev = dev16(pCurrent->y + (x + (i&1) + (y + (i>>1)) * pParam->edged_width) * 16,
2318                                                                    pParam->edged_width);
2319    
2320          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);                                  complexity += MAX(dev, 300);
2321          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);                                  if (dev + IntraThresh < pMB->sad16) {
2322          if (pMB->mvs[0].x > Data.max_dx) pMB->mvs[0].x = Data.max_dx; // this is in case iFcode changed                                          pMB->mode = MODE_INTRA;
2323          if (pMB->mvs[0].x < Data.min_dx) pMB->mvs[0].x = Data.min_dx;                                          if (++intra > ((pParam->mb_height-2)*(pParam->mb_width-2))/2) return I_VOP;
2324          if (pMB->mvs[0].y > Data.max_dy) pMB->mvs[0].y = Data.max_dy;                                  }
         if (pMB->mvs[0].y < Data.min_dy) pMB->mvs[0].y = Data.min_dy;  
   
         CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);  
   
         if (pMB->mode == MODE_INTER4V)  
                 for (i = 1; i < 4; i++) { // all four vectors will be used as four predictions for 16x16 search  
                         pMB->mvs[i].x = EVEN(pMB->mvs[i].x);  
                         pMB->mvs[i].y = EVEN(pMB->mvs[i].y);  
                         if (!(make_mask(pMB->mvs, i)))  
                                 CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);  
                 }  
   
         if (MotionFlags & PMV_USESQUARES16)  
                 MainSearchPtr = SquareSearch;  
         else if (MotionFlags & PMV_ADVANCEDDIAMOND16)  
                 MainSearchPtr = AdvDiamondSearch;  
                 else MainSearchPtr = DiamondSearch;  
2325    
2326          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);                                  if (pMB->mvs[0].x == 0 && pMB->mvs[0].y == 0)
2327                                            if (dev > 500 && pMB->sad16 < 1000)
2328                                                    sSAD += 1000;
2329    
2330          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);                                  sSAD += (dev < 3000) ? pMB->sad16 : pMB->sad16/2; /* blocks with big contrast differences usually have large SAD - while they look very good in b-frames */
2331                            }
2332                    }
2333            }
2334            complexity >>= 7;
2335    
2336          if (inter4v)          sSAD /= complexity + 4*blocks;
                 for(i = 0; i < 4; i++)  
                         Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);  
2337    
2338          if (!(inter4v) ||          if (intraCount > 80 && sSAD > INTRA_THRESH2 ) return I_VOP;
2339                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {          if (sSAD > InterThresh ) return P_VOP;
2340  // INTER MODE          emms();
2341            return B_VOP;
2342    }
2343    
                 pMB->mode = MODE_INTER;  
                 pMB->mvs[0] = pMB->mvs[1]  
                         = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];  
2344    
2345                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =  /* functions which perform BITS-based search/bitcount */
                         pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];  
2346    
2347                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;  static int
2348                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;  findRDinter(SearchData * const Data,
2349                            const MACROBLOCK * const pMBs, const int x, const int y,
2350                            const MBParam * const pParam,
2351                            const uint32_t MotionFlags)
2352    {
2353            int i, iDirection;
2354            int32_t bsad[5];
2355    
2356            CheckCandidate = CheckCandidateRD16;
2357    
2358            if (Data->qpel) {
2359                    for(i = 0; i < 5; i++) {
2360                            Data->currentMV[i].x = Data->currentQMV[i].x/2;
2361                            Data->currentMV[i].y = Data->currentQMV[i].y/2;
2362                    }
2363                    Data->qpel_precision = 1;
2364                    CheckCandidateRD16(Data->currentQMV[0].x, Data->currentQMV[0].y, 255, &iDirection, Data);
2365    
2366                    if (MotionFlags & (XVID_ME_HALFPELREFINE16_RD | XVID_ME_EXTSEARCH_RD)) { /* we have to prepare for halfpixel-precision search */
2367                            for(i = 0; i < 5; i++) bsad[i] = Data->iMinSAD[i];
2368                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2369                                                    pParam->width, pParam->height, Data->iFcode - Data->qpel, 0, Data->rrv);
2370                            Data->qpel_precision = 0;
2371                            if (Data->currentQMV->x & 1 || Data->currentQMV->y & 1)
2372                                    CheckCandidateRD16(Data->currentMV[0].x, Data->currentMV[0].y, 255, &iDirection, Data);
2373                    }
2374    
2375            } else { /* not qpel */
2376    
2377                    CheckCandidateRD16(Data->currentMV[0].x, Data->currentMV[0].y, 255, &iDirection, Data);
2378            }
2379    
2380            if (MotionFlags&XVID_ME_EXTSEARCH_RD) SquareSearch(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
2381    
2382            if (MotionFlags&XVID_ME_HALFPELREFINE16_RD) SubpelRefine(Data);
2383    
2384            if (Data->qpel) {
2385                    if (MotionFlags&(XVID_ME_EXTSEARCH_RD | XVID_ME_HALFPELREFINE16_RD)) { /* there was halfpel-precision search */
2386                            for(i = 0; i < 5; i++) if (bsad[i] > Data->iMinSAD[i]) {
2387                                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; /* we have found a better match */
2388                                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
2389                            }
2390    
2391                            /* preparing for qpel-precision search */
2392                            Data->qpel_precision = 1;
2393                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2394                                            pParam->width, pParam->height, Data->iFcode, 1, 0);
2395                    }
2396                    if (MotionFlags&XVID_ME_QUARTERPELREFINE16_RD) SubpelRefine(Data);
2397            }
2398    
2399            if (MotionFlags&XVID_ME_CHECKPREDICTION_RD) { /* let's check vector equal to prediction */
2400                    VECTOR * v = Data->qpel ? Data->currentQMV : Data->currentMV;
2401                    if (!(Data->predMV.x == v->x && Data->predMV.y == v->y))
2402                            CheckCandidateRD16(Data->predMV.x, Data->predMV.y, 255, &iDirection, Data);
2403            }
2404            return Data->iMinSAD[0];
2405    }
2406    
2407    static int
2408    findRDinter4v(const SearchData * const Data,
2409                                    MACROBLOCK * const pMB, const MACROBLOCK * const pMBs,
2410                                    const int x, const int y,
2411                                    const MBParam * const pParam, const uint32_t MotionFlags,
2412                                    const VECTOR * const backup)
2413    {
2414    
2415            int cbp = 0, bits = 0, t = 0, i, iDirection;
2416            SearchData Data2, *Data8 = &Data2;
2417            int sumx = 0, sumy = 0;
2418            int16_t *in = Data->dctSpace, *coeff = Data->dctSpace + 64;
2419            uint8_t * ptr;
2420    
2421            memcpy(Data8, Data, sizeof(SearchData));
2422            CheckCandidate = CheckCandidateRD8;
2423    
2424            for (i = 0; i < 4; i++) { /* for all luma blocks */
2425    
2426                    Data8->iMinSAD = Data->iMinSAD + i + 1;
2427                    Data8->currentMV = Data->currentMV + i + 1;
2428                    Data8->currentQMV = Data->currentQMV + i + 1;
2429                    Data8->Cur = Data->Cur + 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2430                    Data8->RefP[0] = Data->RefP[0] + 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2431                    Data8->RefP[2] = Data->RefP[2] + 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2432                    Data8->RefP[1] = Data->RefP[1] + 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2433                    Data8->RefP[3] = Data->RefP[3] + 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2434                    *Data8->cbp = (Data->cbp[1] & (1<<(5-i))) ? 1:0; // copy corresponding cbp bit
2435    
2436                    if(Data->qpel) {
2437                            Data8->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, i);
2438                            if (i != 0)     t = d_mv_bits(  Data8->currentQMV->x, Data8->currentQMV->y,
2439                                                                                    Data8->predMV, Data8->iFcode, 0, 0);
2440          } else {          } else {
2441  // INTER4V MODE; all other things are already set in Search8hinted                          Data8->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, i);
2442                  pMB->mode = MODE_INTER4V;                          if (i != 0)     t = d_mv_bits(  Data8->currentMV->x, Data8->currentMV->y,
2443                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                                                                                  Data8->predMV, Data8->iFcode, 0, 0);
2444          }          }
2445    
2446                    get_range(&Data8->min_dx, &Data8->max_dx, &Data8->min_dy, &Data8->max_dy, 2*x + (i&1), 2*y + (i>>1), 8,
2447                                            pParam->width, pParam->height, Data8->iFcode, Data8->qpel, 0);
2448    
2449                    *Data8->iMinSAD += BITS_MULT*t;
2450    
2451                    Data8->qpel_precision = Data8->qpel;
2452                    /* checking the vector which has been found by SAD-based 8x8 search (if it's different than the one found so far) */
2453                    {
2454                            VECTOR *v = Data8->qpel ? Data8->currentQMV : Data8->currentMV;
2455                            if (!MVequal (*v, backup[i+1]) )
2456                                    CheckCandidateRD8(backup[i+1].x, backup[i+1].y, 255, &iDirection, Data8);
2457                    }
2458    
2459                    if (Data8->qpel) {
2460                            if (MotionFlags&XVID_ME_HALFPELREFINE8_RD || (MotionFlags&XVID_ME_EXTSEARCH8 && MotionFlags&XVID_ME_EXTSEARCH_RD)) { /* halfpixel motion search follows */
2461                                    int32_t s = *Data8->iMinSAD;
2462                                    Data8->currentMV->x = Data8->currentQMV->x/2;
2463                                    Data8->currentMV->y = Data8->currentQMV->y/2;
2464                                    Data8->qpel_precision = 0;
2465                                    get_range(&Data8->min_dx, &Data8->max_dx, &Data8->min_dy, &Data8->max_dy, 2*x + (i&1), 2*y + (i>>1), 8,
2466                                                            pParam->width, pParam->height, Data8->iFcode - 1, 0, 0);
2467    
2468                                    if (Data8->currentQMV->x & 1 || Data8->currentQMV->y & 1)
2469                                            CheckCandidateRD8(Data8->currentMV->x, Data8->currentMV->y, 255, &iDirection, Data8);
2470    
2471                                    if (MotionFlags & XVID_ME_EXTSEARCH8 && MotionFlags & XVID_ME_EXTSEARCH_RD)
2472                                            SquareSearch(Data8->currentMV->x, Data8->currentMV->x, Data8, 255);
2473    
2474                                    if (MotionFlags & XVID_ME_HALFPELREFINE8_RD)
2475                                            SubpelRefine(Data8);
2476    
2477                                    if(s > *Data8->iMinSAD) { /* we have found a better match */
2478                                            Data8->currentQMV->x = 2*Data8->currentMV->x;
2479                                            Data8->currentQMV->y = 2*Data8->currentMV->y;
2480                                    }
2481    
2482                                    Data8->qpel_precision = 1;
2483                                    get_range(&Data8->min_dx, &Data8->max_dx, &Data8->min_dy, &Data8->max_dy, 2*x + (i&1), 2*y + (i>>1), 8,
2484                                                            pParam->width, pParam->height, Data8->iFcode, 1, 0);
2485    
2486                            }
2487                            if (MotionFlags & XVID_ME_QUARTERPELREFINE8_RD) SubpelRefine(Data8);
2488    
2489                    } else { /* not qpel */
2490    
2491                            if (MotionFlags & XVID_ME_EXTSEARCH8 && MotionFlags & XVID_ME_EXTSEARCH_RD) /* extsearch */
2492                                    SquareSearch(Data8->currentMV->x, Data8->currentMV->x, Data8, 255);
2493    
2494                            if (MotionFlags & XVID_ME_HALFPELREFINE8_RD)
2495                                    SubpelRefine(Data8); /* halfpel refinement */
2496                    }
2497    
2498                    /* checking vector equal to predicion */
2499                    if (i != 0 && MotionFlags & XVID_ME_CHECKPREDICTION_RD) {
2500                            const VECTOR * v = Data->qpel ? Data8->currentQMV : Data8->currentMV;
2501                            if (!MVequal(*v, Data8->predMV))
2502                                    CheckCandidateRD8(Data8->predMV.x, Data8->predMV.y, 255, &iDirection, Data8);
2503                    }
2504    
2505                    bits += *Data8->iMinSAD;
2506                    if (bits >= Data->iMinSAD[0]) return bits; /* no chances for INTER4V */
2507    
2508                    /* MB structures for INTER4V mode; we have to set them here, we don't have predictor anywhere else */
2509                    if(Data->qpel) {
2510                            pMB->pmvs[i].x = Data8->currentQMV->x - Data8->predMV.x;
2511                            pMB->pmvs[i].y = Data8->currentQMV->y - Data8->predMV.y;
2512                            pMB->qmvs[i] = *Data8->currentQMV;
2513                            sumx += Data8->currentQMV->x/2;
2514                            sumy += Data8->currentQMV->y/2;
2515                    } else {
2516                            pMB->pmvs[i].x = Data8->currentMV->x - Data8->predMV.x;
2517                            pMB->pmvs[i].y = Data8->currentMV->y - Data8->predMV.y;
2518                            sumx += Data8->currentMV->x;
2519                            sumy += Data8->currentMV->y;
2520                    }
2521                    pMB->mvs[i] = *Data8->currentMV;
2522                    pMB->sad8[i] = 4 * *Data8->iMinSAD;
2523                    if (Data8->cbp[0]) cbp |= 1 << (5 - i);
2524    
2525            } /* end - for all luma blocks */
2526    
2527            bits += BITS_MULT*xvid_cbpy_tab[15-(cbp>>2)].len;
2528    
2529            /* let's check chroma */
2530            sumx = (sumx >> 3) + roundtab_76[sumx & 0xf];
2531            sumy = (sumy >> 3) + roundtab_76[sumy & 0xf];
2532    
2533            /* chroma U */
2534            ptr = interpolate8x8_switch2(Data->RefQ + 64, Data->RefP[4], 0, 0, sumx, sumy, Data->iEdgedWidth/2, Data->rounding);
2535            transfer_8to16subro(in, Data->CurU, ptr, Data->iEdgedWidth/2);
2536            bits += Block_CalcBits(coeff, in, Data->dctSpace + 128, Data->iQuant, Data->quant_type, &cbp, 4);
2537    
2538            if (bits >= *Data->iMinSAD) return bits;
2539    
2540            /* chroma V */
2541            ptr = interpolate8x8_switch2(Data->RefQ + 64, Data->RefP[5], 0, 0, sumx, sumy, Data->iEdgedWidth/2, Data->rounding);
2542            transfer_8to16subro(in, Data->CurV, ptr, Data->iEdgedWidth/2);
2543            bits += Block_CalcBits(coeff, in, Data->dctSpace + 128, Data->iQuant, Data->quant_type, &cbp, 5);
2544    
2545            bits += BITS_MULT*mcbpc_inter_tab[(MODE_INTER4V & 7) | ((cbp & 3) << 3)].len;
2546    
2547            *Data->cbp = cbp;
2548            return bits;
2549    }
2550    
2551    static int
2552    findRDintra(const SearchData * const Data)
2553    {
2554            int bits = BITS_MULT*1; /* this one is ac/dc prediction flag bit */
2555            int cbp = 0, i, dc = 0;
2556            int16_t *in = Data->dctSpace, * coeff = Data->dctSpace + 64;
2557    
2558            for(i = 0; i < 4; i++) {
2559                    int s = 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2560                    transfer_8to16copy(in, Data->Cur + s, Data->iEdgedWidth);
2561                    bits += Block_CalcBitsIntra(coeff, in, Data->dctSpace + 128, Data->iQuant, Data->quant_type, &cbp, i, &dc);
2562    
2563                    if (bits >= Data->iMinSAD[0]) return bits;
2564            }
2565    
2566            bits += BITS_MULT*xvid_cbpy_tab[cbp>>2].len;
2567    
2568            /*chroma U */
2569            transfer_8to16copy(in, Data->CurU, Data->iEdgedWidth/2);
2570            bits += Block_CalcBitsIntra(coeff, in, Data->dctSpace + 128, Data->iQuant, Data->quant_type, &cbp, 4, &dc);
2571    
2572            if (bits >= Data->iMinSAD[0]) return bits;
2573    
2574            /* chroma V */
2575            transfer_8to16copy(in, Data->CurV, Data->iEdgedWidth/2);
2576            bits += Block_CalcBitsIntra(coeff, in, Data->dctSpace + 128, Data->iQuant, Data->quant_type, &cbp, 5, &dc);
2577    
2578            bits += BITS_MULT*mcbpc_inter_tab[(MODE_INTRA & 7) | ((cbp & 3) << 3)].len;
2579    
2580            return bits;
2581    }
2582    
2583    static int
2584    findRDgmc(const SearchData * const Data, const IMAGE * const vGMC, const int x, const int y)
2585    {
2586            int bits = BITS_MULT*1; /* this one is mcsel */
2587            int cbp = 0, i;
2588            int16_t *in = Data->dctSpace, * coeff = Data->dctSpace + 64;
2589    
2590            for(i = 0; i < 4; i++) {
2591                    int s = 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2592                    transfer_8to16subro(in, Data->Cur + s, vGMC->y + s + 16*(x+y*Data->iEdgedWidth), Data->iEdgedWidth);
2593                    bits += Block_CalcBits(coeff, in, Data->dctSpace + 128, Data->iQuant, Data->quant_type, &cbp, i);
2594                    if (bits >= Data->iMinSAD[0]) return bits;
2595            }
2596    
2597            bits += BITS_MULT*xvid_cbpy_tab[15-(cbp>>2)].len;
2598    
2599            /*chroma U */
2600            transfer_8to16subro(in, Data->CurU, vGMC->u + 8*(x+y*(Data->iEdgedWidth/2)), Data->iEdgedWidth/2);
2601            bits += Block_CalcBits(coeff, in, Data->dctSpace + 128, Data->iQuant, Data->quant_type, &cbp, 4);
2602    
2603            if (bits >= Data->iMinSAD[0]) return bits;
2604    
2605            /* chroma V */
2606            transfer_8to16subro(in, Data->CurV , vGMC->v + 8*(x+y*(Data->iEdgedWidth/2)), Data->iEdgedWidth/2);
2607            bits += Block_CalcBits(coeff, in, Data->dctSpace + 128, Data->iQuant, Data->quant_type, &cbp, 5);
2608    
2609            bits += BITS_MULT*mcbpc_inter_tab[(MODE_INTER & 7) | ((cbp & 3) << 3)].len;
2610    
2611            *Data->cbp = cbp;
2612    
2613            return bits;
2614    }
2615    
2616    
2617    
2618    
2619    static __inline void
2620    GMEanalyzeMB (  const uint8_t * const pCur,
2621                                    const uint8_t * const pRef,
2622                                    const uint8_t * const pRefH,
2623                                    const uint8_t * const pRefV,
2624                                    const uint8_t * const pRefHV,
2625                                    const int x,
2626                                    const int y,
2627                                    const MBParam * const pParam,
2628                                    MACROBLOCK * const pMBs,
2629                                    SearchData * const Data)
2630    {
2631    
2632            int i=0;
2633            MACROBLOCK * const pMB = &pMBs[x + y * pParam->mb_width];
2634    
2635            Data->iMinSAD[0] = MV_MAX_ERROR;
2636    
2637            Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
2638    
2639            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2640                                    pParam->width, pParam->height, 16, 0, 0);
2641    
2642            Data->Cur = pCur + 16*(x + y * pParam->edged_width);
2643            Data->RefP[0] = pRef + 16*(x + y * pParam->edged_width);
2644            Data->RefP[1] = pRefV + 16*(x + y * pParam->edged_width);
2645            Data->RefP[2] = pRefH + 16*(x + y * pParam->edged_width);
2646            Data->RefP[3] = pRefHV + 16*(x + y * pParam->edged_width);
2647    
2648            Data->currentMV[0].x = Data->currentMV[0].y = 0;
2649            CheckCandidate16I(0, 0, 255, &i, Data);
2650    
2651            if ( (Data->predMV.x !=0) || (Data->predMV.y != 0) )
2652                    CheckCandidate16I(Data->predMV.x, Data->predMV.y, 255, &i, Data);
2653    
2654            AdvDiamondSearch(Data->currentMV[0].x, Data->currentMV[0].y, Data, 255);
2655    
2656            SubpelRefine(Data);
2657    
2658    
2659            /* for QPel halfpel positions are worse than in halfpel mode :( */
2660    /*      if (Data->qpel) {
2661                    Data->currentQMV->x = 2*Data->currentMV->x;
2662                    Data->currentQMV->y = 2*Data->currentMV->y;
2663                    Data->qpel_precision = 1;
2664                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2665                                            pParam->width, pParam->height, iFcode, 1, 0);
2666                    SubpelRefine(Data);
2667            }
2668    */
2669    
2670            pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
2671            pMB->sad16 = Data->iMinSAD[0];
2672            pMB->mode = MODE_INTER;
2673            pMB->sad16 += 10*d_mv_bits(pMB->mvs[0].x, pMB->mvs[0].y, Data->predMV, Data->iFcode, 0, 0);
2674            return;
2675  }  }
2676    
2677  void  void
2678  MotionEstimationHinted( MBParam * const pParam,  GMEanalysis(const MBParam * const pParam,
2679                                                  FRAMEINFO * const current,                          const FRAMEINFO * const current,
2680                                                  FRAMEINFO * const reference,                          const FRAMEINFO * const reference,
2681                                                  const IMAGE * const pRefH,                                                  const IMAGE * const pRefH,
2682                                                  const IMAGE * const pRefV,                                                  const IMAGE * const pRefV,
2683                                                  const IMAGE * const pRefHV)                                                  const IMAGE * const pRefHV)
2684  {  {
2685            uint32_t x, y;
2686          MACROBLOCK *const pMBs = current->mbs;          MACROBLOCK *const pMBs = current->mbs;
2687          const IMAGE *const pCurrent = &current->image;          const IMAGE *const pCurrent = &current->image;
2688          const IMAGE *const pRef = &reference->image;          const IMAGE * const pReference = &reference->image;
2689    
2690          uint32_t x, y;          int32_t iMinSAD[5], temp[5];
2691            VECTOR currentMV[5];
2692            SearchData Data;
2693            memset(&Data, 0, sizeof(SearchData));
2694    
2695            Data.iEdgedWidth = pParam->edged_width;
2696            Data.rounding = pParam->m_rounding_type;
2697    
2698            Data.currentMV = &currentMV[0];
2699            Data.iMinSAD = &iMinSAD[0];
2700            Data.iFcode = current->fcode;
2701            Data.temp = temp;
2702    
2703            CheckCandidate = CheckCandidate16I;
2704    
2705          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
2706    
2707          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
2708                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
2709    
2710                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          GMEanalyzeMB(pCurrent->y, pReference->y, pRefH->y, pRefV->y, pRefHV->y, x, y, pParam, pMBs, &Data);
2711                    }
2712            }
2713            return;
2714    }
2715    
2716    
2717    WARPPOINTS
2718    GlobalMotionEst(MACROBLOCK * const pMBs,
2719                                    const MBParam * const pParam,
2720                                    const FRAMEINFO * const current,
2721                                    const FRAMEINFO * const reference,
2722                                    const IMAGE * const pRefH,
2723                                    const IMAGE * const pRefV,
2724                                    const IMAGE * const pRefHV)
2725    {
2726    
2727            const int deltax=8;             // upper bound for difference between a MV and it's neighbour MVs
2728            const int deltay=8;
2729            const unsigned int gradx=512;           // lower bound for gradient in MB (ignore "flat" blocks)
2730            const unsigned int grady=512;
2731    
2732            double sol[4] = { 0., 0., 0., 0. };
2733    
2734            WARPPOINTS gmc;
2735    
2736            uint32_t mx, my;
2737    
2738  //intra mode is copied from the first pass. At least for the time being          int MBh = pParam->mb_height;
2739                          if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;          int MBw = pParam->mb_width;
2740            const int minblocks = 9; //MBh*MBw/32+3;                /* just some reasonable number 3% + 3 */
2741            const int maxblocks = MBh*MBw/4;                /* just some reasonable number 3% + 3 */
2742    
2743                          if (!(current->global_flags & XVID_LUMIMASKING)) {          int num=0;
2744                                  pMB->dquant = NO_CHANGE;          int oldnum;
                                 pMB->quant = current->quant; }  
   
                         SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,  
                                                         y, current->motion_flags, pMB->quant,  
                                                         current->fcode, pParam, pMBs,  
                                                         current->global_flags & XVID_INTER4V, pMB);  
2745    
2746            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;
2747    
2748            GMEanalysis(pParam,current, reference, pRefH, pRefV, pRefHV);
2749    
2750            /* block based ME isn't done, yet, so do a quick presearch */
2751    
2752    // filter mask of all blocks
2753    
2754            for (my = 0; my < (uint32_t)MBh; my++)
2755            for (mx = 0; mx < (uint32_t)MBw; mx++)
2756            {
2757                    const int mbnum = mx + my * MBw;
2758                            pMBs[mbnum].mcsel = 0;
2759            }
2760    
2761    
2762            for (my = 1; my < (uint32_t)MBh-1; my++) /* ignore boundary blocks */
2763            for (mx = 1; mx < (uint32_t)MBw-1; mx++) /* theirs MVs are often wrong */
2764            {
2765                    const int mbnum = mx + my * MBw;
2766                    MACROBLOCK *const pMB = &pMBs[mbnum];
2767                    const VECTOR mv = pMB->mvs[0];
2768    
2769                    /* don't use object boundaries */
2770                    if   ( (abs(mv.x -   (pMB-1)->mvs[0].x) < deltax)
2771                            && (abs(mv.y -   (pMB-1)->mvs[0].y) < deltay)
2772                            && (abs(mv.x -   (pMB+1)->mvs[0].x) < deltax)
2773                            && (abs(mv.y -   (pMB+1)->mvs[0].y) < deltay)
2774                            && (abs(mv.x - (pMB-MBw)->mvs[0].x) < deltax)
2775                            && (abs(mv.y - (pMB-MBw)->mvs[0].y) < deltay)
2776                            && (abs(mv.x - (pMB+MBw)->mvs[0].x) < deltax)
2777                            && (abs(mv.y - (pMB+MBw)->mvs[0].y) < deltay) )
2778                    {       const int iEdgedWidth = pParam->edged_width;
2779                            const uint8_t *const pCur = current->image.y + 16*(my*iEdgedWidth + mx);
2780                            if ( (sad16 ( pCur, pCur+1 , iEdgedWidth, 65536) >= gradx )
2781                             &&  (sad16 ( pCur, pCur+iEdgedWidth, iEdgedWidth, 65536) >= grady ) )
2782                             {      pMB->mcsel = 1;
2783                                    num++;
2784                  }                  }
2785    
2786                    /* only use "structured" blocks */
2787          }          }
2788  }  }
2789            emms();
2790    
2791  static __inline int          /*      further filtering would be possible, but during iteration, remaining
2792  MEanalyzeMB (   const uint8_t * const pRef,                  outliers usually are removed, too */
2793                                  const uint8_t * const pCur,  
2794                                  const int x,          if (num>= minblocks)
2795                                  const int y,          do {            /* until convergence */
2796                                  const uint32_t iFcode,                  double DtimesF[4];
2797                                  const MBParam * const pParam,                  double a,b,c,n,invdenom;
2798                                  const MACROBLOCK * const pMBs,                  double meanx,meany;
2799                                  MACROBLOCK * const pMB)  
2800                    a = b = c = n = 0;
2801                    DtimesF[0] = DtimesF[1] = DtimesF[2] = DtimesF[3] = 0.;
2802                    for (my = 1; my < (uint32_t)MBh-1; my++)
2803                    for (mx = 1; mx < (uint32_t)MBw-1; mx++)
2804  {  {
2805                            const int mbnum = mx + my * MBw;
2806                            const VECTOR mv = pMBs[mbnum].mvs[0];
2807    
2808          const int32_t iEdgedWidth = pParam->edged_width;                          if (!pMBs[mbnum].mcsel)
2809          int i, mask;                                  continue;
         VECTOR currentMV, pmv[3];  
         int32_t iMinSAD = MV_MAX_ERROR;  
         SearchData Data;  
2810    
2811          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);                          n++;
2812          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,                          a += 16*mx+8;
2813                                  pParam->width, pParam->height, iFcode);                          b += 16*my+8;
2814                            c += (16*mx+8)*(16*mx+8)+(16*my+8)*(16*my+8);
2815    
2816          Data.Cur = pCur + (x + y * iEdgedWidth) * 16;                          DtimesF[0] += (double)mv.x;
2817          Data.iEdgedWidth = iEdgedWidth;                          DtimesF[1] += (double)mv.x*(16*mx+8) + (double)mv.y*(16*my+8);
2818          Data.currentMV = &currentMV;                          DtimesF[2] += (double)mv.x*(16*my+8) - (double)mv.y*(16*mx+8);
2819          Data.iMinSAD = &iMinSAD;                          DtimesF[3] += (double)mv.y;
2820          Data.Ref = pRef + (x + iEdgedWidth*y)*16;                  }
         Data.iQuant = 2;  
         Data.iFcode = iFcode;  
2821    
2822          CheckCandidate = CheckCandidate16no4vI;          invdenom = a*a+b*b-c*n;
2823    
2824          pmv[1].x = EVEN(pMB->mvs[0].x);  /* Solve the system:    sol = (D'*E*D)^{-1} D'*E*F   */
2825          pmv[1].y = EVEN(pMB->mvs[0].y);  /* D'*E*F has been calculated in the same loop as matrix */
         pmv[0].x = EVEN(Data.predMV.x);  
         pmv[0].y = EVEN(Data.predMV.y);  
         pmv[2].x = pmv[2].y = 0;  
2826    
2827          CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, &Data);          sol[0] = -c*DtimesF[0] + a*DtimesF[1] + b*DtimesF[2];
2828          if (!(mask = make_mask(pmv, 1)))          sol[1] =  a*DtimesF[0] - n*DtimesF[1]                           + b*DtimesF[3];
2829                  CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, &Data);          sol[2] =  b*DtimesF[0]                          - n*DtimesF[2] - a*DtimesF[3];
2830          if (!(mask = make_mask(pmv, 2)))          sol[3] =                                 b*DtimesF[1] - a*DtimesF[2] - c*DtimesF[3];
                 CheckCandidate16no4vI(0, 0, mask, &i, &Data);  
2831    
2832          DiamondSearch(currentMV.x, currentMV.y, &Data, i);          sol[0] /= invdenom;
2833            sol[1] /= invdenom;
2834            sol[2] /= invdenom;
2835            sol[3] /= invdenom;
2836    
2837          pMB->mvs[0] = pMB->mvs[1]          meanx = meany = 0.;
2838                          = pMB->mvs[2] = pMB->mvs[3] = currentMV; // all, for future get_pmv()          oldnum = 0;
2839            for (my = 1; my < (uint32_t)MBh-1; my++)
2840                    for (mx = 1; mx < (uint32_t)MBw-1; mx++)
2841                    {
2842                            const int mbnum = mx + my * MBw;
2843                            const VECTOR mv = pMBs[mbnum].mvs[0];
2844    
2845          return iMinSAD;                          if (!pMBs[mbnum].mcsel)
2846                                    continue;
2847    
2848                            oldnum++;
2849                            meanx += fabs(( sol[0] + (16*mx+8)*sol[1] + (16*my+8)*sol[2] ) - (double)mv.x );
2850                            meany += fabs(( sol[3] - (16*mx+8)*sol[2] + (16*my+8)*sol[1] ) - (double)mv.y );
2851  }  }
2852    
2853  #define INTRA_THRESH    1350          if (4*meanx > oldnum)   /* better fit than 0.25 (=1/4pel) is useless */
2854  #define INTER_THRESH    900                  meanx /= oldnum;
2855            else
2856                    meanx = 0.25;
2857    
2858            if (4*meany > oldnum)
2859                    meany /= oldnum;
2860            else
2861                    meany = 0.25;
2862    
2863            num = 0;
2864            for (my = 0; my < (uint32_t)MBh; my++)
2865                    for (mx = 0; mx < (uint32_t)MBw; mx++)
2866                    {
2867                            const int mbnum = mx + my * MBw;
2868                            const VECTOR mv = pMBs[mbnum].mvs[0];
2869    
2870                            if (!pMBs[mbnum].mcsel)
2871                                    continue;
2872    
2873                            if  ( ( fabs(( sol[0] + (16*mx+8)*sol[1] + (16*my+8)*sol[2] ) - (double)mv.x ) > meanx )
2874                                    || ( fabs(( sol[3] - (16*mx+8)*sol[2] + (16*my+8)*sol[1] ) - (double)mv.y ) > meany ) )
2875                                    pMBs[mbnum].mcsel=0;
2876                            else
2877                                    num++;
2878                    }
2879    
2880            } while ( (oldnum != num) && (num>= minblocks) );
2881    
2882            if (num < minblocks)
2883            {
2884                    const int iEdgedWidth = pParam->edged_width;
2885                    num = 0;
2886    
2887    /*              fprintf(stderr,"Warning! Unreliable GME (%d/%d blocks), falling back to translation.\n",num,MBh*MBw);
2888    */
2889                    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;
2890    
2891                    if (!(current->motion_flags & XVID_ME_GME_REFINE))
2892                            return gmc;
2893    
2894                    for (my = 1; my < (uint32_t)MBh-1; my++) /* ignore boundary blocks */
2895                    for (mx = 1; mx < (uint32_t)MBw-1; mx++) /* theirs MVs are often wrong */
2896                    {
2897                            const int mbnum = mx + my * MBw;
2898                            MACROBLOCK *const pMB = &pMBs[mbnum];
2899                            const uint8_t *const pCur = current->image.y + 16*(my*iEdgedWidth + mx);
2900                            if ( (sad16 ( pCur, pCur+1 , iEdgedWidth, 65536) >= gradx )
2901                             &&  (sad16 ( pCur, pCur+iEdgedWidth, iEdgedWidth, 65536) >= grady ) )
2902                             {      pMB->mcsel = 1;
2903                                    gmc.duv[0].x += pMB->mvs[0].x;
2904                                    gmc.duv[0].y += pMB->mvs[0].y;
2905                                    num++;
2906                             }
2907                    }
2908    
2909                    if (gmc.duv[0].x)
2910                            gmc.duv[0].x /= num;
2911                    if (gmc.duv[0].y)
2912                            gmc.duv[0].y /= num;
2913            } else {
2914    
2915                    gmc.duv[0].x=(int)(sol[0]+0.5);
2916                    gmc.duv[0].y=(int)(sol[3]+0.5);
2917    
2918                    gmc.duv[1].x=(int)(sol[1]*pParam->width+0.5);
2919                    gmc.duv[1].y=(int)(-sol[2]*pParam->width+0.5);
2920    
2921                    gmc.duv[2].x=-gmc.duv[1].y;             /* two warp points only */
2922                    gmc.duv[2].y=gmc.duv[1].x;
2923            }
2924            if (num>maxblocks)
2925            {       for (my = 1; my < (uint32_t)MBh-1; my++)
2926                    for (mx = 1; mx < (uint32_t)MBw-1; mx++)
2927                    {
2928                            const int mbnum = mx + my * MBw;
2929                            if (pMBs[mbnum-1].mcsel)
2930                                    pMBs[mbnum].mcsel=0;
2931                            else
2932                                    if (pMBs[mbnum-MBw].mcsel)
2933                                            pMBs[mbnum].mcsel=0;
2934                    }
2935            }
2936            return gmc;
2937    }
2938    
2939  int  int
2940  MEanalysis(     const IMAGE * const pRef,  GlobalMotionEstRefine(
2941                          const IMAGE * const pCurrent,                                  WARPPOINTS *const startwp,
                         MBParam * const pParam,  
2942                          MACROBLOCK * const pMBs,                          MACROBLOCK * const pMBs,
2943                          const uint32_t iFcode)                                  const MBParam * const pParam,
2944                                    const FRAMEINFO * const current,
2945                                    const FRAMEINFO * const reference,
2946                                    const IMAGE * const pCurr,
2947                                    const IMAGE * const pRef,
2948                                    const IMAGE * const pRefH,
2949                                    const IMAGE * const pRefV,
2950                                    const IMAGE * const pRefHV)
2951  {  {
2952          uint32_t x, y, intra = 0;          uint8_t* GMCblock = (uint8_t*)malloc(16*pParam->edged_width);
2953          int sSAD = 0;          WARPPOINTS bestwp=*startwp;
2954            WARPPOINTS centerwp,currwp;
2955            int gmcminSAD=0;
2956            int gmcSAD=0;
2957            int direction;
2958    //      int mx,my;
2959    
2960    /* use many blocks... */
2961    /*              for (my = 0; my < (uint32_t)pParam->mb_height; my++)
2962                    for (mx = 0; mx < (uint32_t)pParam->mb_width; mx++)
2963                    {
2964                            const int mbnum = mx + my * pParam->mb_width;
2965                            pMBs[mbnum].mcsel=1;
2966                    }
2967    */
2968    
2969          if (sadInit) (*sadInit) ();  /* or rather don't use too many blocks... */
2970    /*
2971                    for (my = 1; my < (uint32_t)MBh-1; my++)
2972                    for (mx = 1; mx < (uint32_t)MBw-1; mx++)
2973                    {
2974                            const int mbnum = mx + my * MBw;
2975                            if (MBmask[mbnum-1])
2976                                    MBmask[mbnum-1]=0;
2977                            else
2978                                    if (MBmask[mbnum-MBw])
2979                                            MBmask[mbnum-1]=0;
2980    
2981          for (y = 0; y < pParam->mb_height-1; y++) {                  }
2982                  for (x = 0; x < pParam->mb_width; x++) {  */
2983                          int sad, dev;                  gmcminSAD = globalSAD(&bestwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
2984    
2985                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                  if ( (reference->coding_type == S_VOP)
2986                            && ( (reference->warp.duv[1].x != bestwp.duv[1].x)
2987                              || (reference->warp.duv[1].y != bestwp.duv[1].y)
2988                              || (reference->warp.duv[0].x != bestwp.duv[0].x)
2989                              || (reference->warp.duv[0].y != bestwp.duv[0].y)
2990                              || (reference->warp.duv[2].x != bestwp.duv[2].x)
2991                              || (reference->warp.duv[2].y != bestwp.duv[2].y) ) )
2992                    {
2993                            gmcSAD = globalSAD(&reference->warp, pParam, pMBs,
2994                                                                    current, pRef, pCurr, GMCblock);
2995    
2996                            if (gmcSAD < gmcminSAD)
2997                            {       bestwp = reference->warp;
2998                                    gmcminSAD = gmcSAD;
2999                            }
3000                    }
3001    
3002            do {
3003                    direction = 0;
3004                    centerwp = bestwp;
3005    
3006                          sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,                  currwp = centerwp;
                                                                 iFcode, pParam, pMBs, pMB);  
3007    
3008                          if ( x != 0 && y != 0 && x != pParam->mb_width-1 ) { //no edge macroblocks, they just don't work                  currwp.duv[0].x--;
3009                                  if (sad > INTRA_THRESH) {                  gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3010                                          dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,                  if (gmcSAD < gmcminSAD)
3011                                                                    pParam->edged_width);                  {       bestwp = currwp;
3012                                          if (dev + INTRA_THRESH < sad) intra++;                          gmcminSAD = gmcSAD;
3013                                          if (intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame                          direction = 1;
3014                                  }                                  }
3015                                  sSAD += sad;                  else
3016                    {
3017                    currwp = centerwp; currwp.duv[0].x++;
3018                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3019                    if (gmcSAD < gmcminSAD)
3020                    {       bestwp = currwp;
3021                            gmcminSAD = gmcSAD;
3022                            direction = 2;
3023                          }                          }
3024                    }
3025                    if (direction) continue;
3026    
3027                    currwp = centerwp; currwp.duv[0].y--;
3028                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3029                    if (gmcSAD < gmcminSAD)
3030                    {       bestwp = currwp;
3031                            gmcminSAD = gmcSAD;
3032                            direction = 4;
3033                  }                  }
3034                    else
3035                    {
3036                    currwp = centerwp; currwp.duv[0].y++;
3037                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3038                    if (gmcSAD < gmcminSAD)
3039                    {       bestwp = currwp;
3040                            gmcminSAD = gmcSAD;
3041                            direction = 8;
3042          }          }
3043          sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);                  }
3044          if (sSAD > INTER_THRESH ) return 1; //P frame                  if (direction) continue;
3045          emms();  
3046          return 0; // B frame                  currwp = centerwp; currwp.duv[1].x++;
3047                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3048                    if (gmcSAD < gmcminSAD)
3049                    {       bestwp = currwp;
3050                            gmcminSAD = gmcSAD;
3051                            direction = 32;
3052                    }
3053                    currwp.duv[2].y++;
3054                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3055                    if (gmcSAD < gmcminSAD)
3056                    {       bestwp = currwp;
3057                            gmcminSAD = gmcSAD;
3058                            direction = 1024;
3059                    }
3060    
3061                    currwp = centerwp; currwp.duv[1].x--;
3062                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3063                    if (gmcSAD < gmcminSAD)
3064                    {       bestwp = currwp;
3065                            gmcminSAD = gmcSAD;
3066                            direction = 16;
3067                    }
3068                    else
3069                    {
3070                    currwp = centerwp; currwp.duv[1].x++;
3071                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3072                    if (gmcSAD < gmcminSAD)
3073                    {       bestwp = currwp;
3074                            gmcminSAD = gmcSAD;
3075                            direction = 32;
3076                    }
3077                    }
3078                    if (direction) continue;
3079    
3080    
3081                    currwp = centerwp; currwp.duv[1].y--;
3082                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3083                    if (gmcSAD < gmcminSAD)
3084                    {       bestwp = currwp;
3085                            gmcminSAD = gmcSAD;
3086                            direction = 64;
3087                    }
3088                    else
3089                    {
3090                    currwp = centerwp; currwp.duv[1].y++;
3091                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3092                    if (gmcSAD < gmcminSAD)
3093                    {       bestwp = currwp;
3094                            gmcminSAD = gmcSAD;
3095                            direction = 128;
3096                    }
3097                    }
3098                    if (direction) continue;
3099    
3100                    currwp = centerwp; currwp.duv[2].x--;
3101                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3102                    if (gmcSAD < gmcminSAD)
3103                    {       bestwp = currwp;
3104                            gmcminSAD = gmcSAD;
3105                            direction = 256;
3106                    }
3107                    else
3108                    {
3109                    currwp = centerwp; currwp.duv[2].x++;
3110                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3111                    if (gmcSAD < gmcminSAD)
3112                    {       bestwp = currwp;
3113                            gmcminSAD = gmcSAD;
3114                            direction = 512;
3115                    }
3116                    }
3117                    if (direction) continue;
3118    
3119                    currwp = centerwp; currwp.duv[2].y--;
3120                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3121                    if (gmcSAD < gmcminSAD)
3122                    {       bestwp = currwp;
3123                            gmcminSAD = gmcSAD;
3124                            direction = 1024;
3125                    }
3126                    else
3127                    {
3128                    currwp = centerwp; currwp.duv[2].y++;
3129                    gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
3130                    if (gmcSAD < gmcminSAD)
3131                    {       bestwp = currwp;
3132                            gmcminSAD = gmcSAD;
3133                            direction = 2048;
3134  }  }
3135                    }
3136            } while (direction);
3137            free(GMCblock);
3138    
3139            *startwp = bestwp;
3140    
3141            return gmcminSAD;
3142    }
3143    
3144    int
3145    globalSAD(const WARPPOINTS *const wp,
3146                      const MBParam * const pParam,
3147                      const MACROBLOCK * const pMBs,
3148                      const FRAMEINFO * const current,
3149                      const IMAGE * const pRef,
3150                      const IMAGE * const pCurr,
3151                      uint8_t *const GMCblock)
3152    {
3153            NEW_GMC_DATA gmc_data;
3154            int iSAD, gmcSAD=0;
3155            int num=0;
3156            unsigned int mx, my;
3157    
3158            generate_GMCparameters( 3, 3, wp, pParam->width, pParam->height, &gmc_data);
3159    
3160            for (my = 0; my < (uint32_t)pParam->mb_height; my++)
3161                    for (mx = 0; mx < (uint32_t)pParam->mb_width; mx++) {
3162    
3163                    const int mbnum = mx + my * pParam->mb_width;
3164                    const int iEdgedWidth = pParam->edged_width;
3165    
3166                    if (!pMBs[mbnum].mcsel)
3167                            continue;
3168    
3169                    gmc_data.predict_16x16(&gmc_data, GMCblock,
3170                                                    pRef->y,
3171                                                    iEdgedWidth,
3172                                                    iEdgedWidth,
3173                                                    mx, my,
3174                                                    pParam->m_rounding_type);
3175    
3176                    iSAD = sad16 ( pCurr->y + 16*(my*iEdgedWidth + mx),
3177                                                    GMCblock , iEdgedWidth, 65536);
3178                    iSAD -= pMBs[mbnum].sad16;
3179    
3180                    if (iSAD<0)
3181                            gmcSAD += iSAD;
3182                    num++;
3183            }
3184            return gmcSAD;
3185    }
3186    

Legend:
Removed from v.1.44.2.2  
changed lines
  Added in v.1.58.2.26

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