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

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

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

revision 530, Mon Sep 23 20:36:02 2002 UTC revision 768, Thu Jan 9 11:36:33 2003 UTC
# Line 31  Line 31 
31  #include <assert.h>  #include <assert.h>
32  #include <stdio.h>  #include <stdio.h>
33  #include <stdlib.h>  #include <stdlib.h>
34    #include <string.h>     // memcpy
35    
36  #include "../encoder.h"  #include "../encoder.h"
37  #include "../utils/mbfunctions.h"  #include "../utils/mbfunctions.h"
38  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
39  #include "../global.h"  #include "../global.h"
40  #include "../utils/timer.h"  #include "../utils/timer.h"
41    #include "../image/interpolate8x8.h"
42  #include "motion_est.h"  #include "motion_est.h"
43  #include "motion.h"  #include "motion.h"
44  #include "sad.h"  #include "sad.h"
45    #include "../utils/emms.h"
46    
47  #define INITIAL_SKIP_THRESH     (10)  #define INITIAL_SKIP_THRESH     (10)
48  #define FINAL_SKIP_THRESH       (50)  #define FINAL_SKIP_THRESH       (50)
49  #define MAX_SAD00_FOR_SKIP      (20)  #define MAX_SAD00_FOR_SKIP      (20)
50  #define MAX_CHROMA_SAD_FOR_SKIP (18)  #define MAX_CHROMA_SAD_FOR_SKIP (22)
 #define SKIP_THRESH_B (10)  
51    
52  #define CHECK_CANDIDATE(X,Y,D) { \  #define CHECK_CANDIDATE(X,Y,D) { \
53  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }
54    
55  #define iDiamondSize 2  static __inline uint32_t
56    d_mv_bits(int x, int y, const VECTOR pred, const uint32_t iFcode, const int qpel, const int rrv)
 //FILE * debug;  
   
 static __inline int  
 d_mv_bits(int x, int y, const uint32_t iFcode)  
57  {  {
58          int xb, yb;          int xb, yb;
59            x += x * qpel; y += y * qpel;
60            if (rrv) { x = RRV_MV_SCALEDOWN(x); y = RRV_MV_SCALEDOWN(y); }
61            x -= pred.x;
62            y -= pred.y;
63    
64          if (x == 0) xb = 1;          if (x) {
65          else {                  x = ABS(x);
                 if (x < 0) x = -x;  
66                  x += (1 << (iFcode - 1)) - 1;                  x += (1 << (iFcode - 1)) - 1;
67                  x >>= (iFcode - 1);                  x >>= (iFcode - 1);
68                  if (x > 32) x = 32;                  if (x > 32) x = 32;
69                  xb = mvtab[x] + iFcode;                  xb = mvtab[x] + iFcode;
70          }          } else xb = 1;
71    
72          if (y == 0) yb = 1;          if (y) {
73          else {                  y = ABS(y);
                 if (y < 0) y = -y;  
74                  y += (1 << (iFcode - 1)) - 1;                  y += (1 << (iFcode - 1)) - 1;
75                  y >>= (iFcode - 1);                  y >>= (iFcode - 1);
76                  if (y > 32) y = 32;                  if (y > 32) y = 32;
77                  yb = mvtab[y] + iFcode;                  yb = mvtab[y] + iFcode;
78          }          } else yb = 1;
79          return xb + yb;          return xb + yb;
80  }  }
81    
82  /* CHACK_CANDIATE FUNCTIONS START */  static int32_t
83    ChromaSAD(int dx, int dy, const SearchData * const data)
84    {
85            int sad;
86            const uint32_t stride = data->iEdgedWidth/2;
87    
88            if (dx == data->temp[5] && dy == data->temp[6]) return data->temp[7]; //it has been checked recently
89            data->temp[5] = dx; data->temp[6] = dy; // backup
90    
91            switch (((dx & 1) << 1) | (dy & 1))     {
92                    case 0:
93                            dx = dx / 2; dy = dy / 2;
94                            sad = sad8(data->CurU, data->RefCU + dy * stride + dx, stride);
95                            sad += sad8(data->CurV, data->RefCV + dy * stride + dx, stride);
96                            break;
97                    case 1:
98                            dx = dx / 2; dy = (dy - 1) / 2;
99                            sad = sad8bi(data->CurU, data->RefCU + dy * stride + dx, data->RefCU + (dy+1) * stride + dx, stride);
100                            sad += sad8bi(data->CurV, data->RefCV + dy * stride + dx, data->RefCV + (dy+1) * stride + dx, stride);
101                            break;
102                    case 2:
103                            dx = (dx - 1) / 2; dy = dy / 2;
104                            sad = sad8bi(data->CurU, data->RefCU + dy * stride + dx, data->RefCU + dy * stride + dx+1, stride);
105                            sad += sad8bi(data->CurV, data->RefCV + dy * stride + dx, data->RefCV + dy * stride + dx+1, stride);
106                            break;
107                    default:
108                            dx = (dx - 1) / 2; dy = (dy - 1) / 2;
109                            interpolate8x8_halfpel_hv(data->RefQ, data->RefCU + dy * stride + dx, stride, data->rounding);
110                            sad = sad8(data->CurU, data->RefQ, stride);
111    
112                            interpolate8x8_halfpel_hv(data->RefQ, data->RefCV + dy * stride + dx, stride, data->rounding);
113                            sad += sad8(data->CurV, data->RefQ, stride);
114                            break;
115            }
116            data->temp[7] = sad; //backup, part 2
117            return sad;
118    }
119    
120    static __inline const uint8_t *
121    GetReferenceB(const int x, const int y, const uint32_t dir, const SearchData * const data)
122    {
123    //      dir : 0 = forward, 1 = backward
124            switch ( (dir << 2) | ((x&1)<<1) | (y&1) ) {
125                    case 0 : return data->Ref + x/2 + (y/2)*(data->iEdgedWidth);
126                    case 1 : return data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth);
127                    case 2 : return data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth);
128                    case 3 : return data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth);
129                    case 4 : return data->bRef + x/2 + (y/2)*(data->iEdgedWidth);
130                    case 5 : return data->bRefV + x/2 + ((y-1)/2)*(data->iEdgedWidth);
131                    case 6 : return data->bRefH + (x-1)/2 + (y/2)*(data->iEdgedWidth);
132                    default : return data->bRefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth);
133            }
134    }
135    
136    // this is a simpler copy of GetReferenceB, but as it's __inline anyway, we can keep the two separate
137    static __inline const uint8_t *
138    GetReference(const int x, const int y, const SearchData * const data)
139    {
140            switch ( ((x&1)<<1) | (y&1) ) {
141                    case 0 : return data->Ref + x/2 + (y/2)*(data->iEdgedWidth);
142                    case 1 : return data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth);
143                    case 2 : return data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth);
144                    default : return data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth);
145            }
146    }
147    
148    static uint8_t *
149    Interpolate8x8qpel(const int x, const int y, const uint32_t block, const uint32_t dir, const SearchData * const data)
150    {
151    // create or find a qpel-precision reference picture; return pointer to it
152            uint8_t * Reference = data->RefQ + 16*dir;
153            const uint32_t iEdgedWidth = data->iEdgedWidth;
154            const uint32_t rounding = data->rounding;
155            const int halfpel_x = x/2;
156            const int halfpel_y = y/2;
157            const uint8_t *ref1, *ref2, *ref3, *ref4;
158    
159            ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
160            ref1 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
161            switch( ((x&1)<<1) + (y&1) ) {
162            case 0: // pure halfpel position
163                    return (uint8_t *) ref1;
164                    break;
165    
166            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
167                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
168                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
169                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
170                    break;
171    
172            case 2: // x qpel, y halfpel - left or right during qpel refinement
173                    ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
174                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
175                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
176                    break;
177    
178            default: // x and y in qpel resolution - the "corners" (top left/right and
179                             // bottom left/right) during qpel refinement
180                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
181                    ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
182                    ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
183                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
184                    ref3 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
185                    ref4 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
186                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
187                    break;
188            }
189            return Reference;
190    }
191    
192    static uint8_t *
193    Interpolate16x16qpel(const int x, const int y, const uint32_t dir, const SearchData * const data)
194    {
195    // create or find a qpel-precision reference picture; return pointer to it
196            uint8_t * Reference = data->RefQ + 16*dir;
197            const uint32_t iEdgedWidth = data->iEdgedWidth;
198            const uint32_t rounding = data->rounding;
199            const int halfpel_x = x/2;
200            const int halfpel_y = y/2;
201            const uint8_t *ref1, *ref2, *ref3, *ref4;
202    
203            ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
204            switch( ((x&1)<<1) + (y&1) ) {
205            case 0: // pure halfpel position
206                    return (uint8_t *) ref1;
207            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
208                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
209                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
210                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
211                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
212                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
213                    break;
214    
215            case 2: // x qpel, y halfpel - left or right during qpel refinement
216                    ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
217                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
218                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
219                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
220                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
221                    break;
222    
223            default: // x and y in qpel resolution - the "corners" (top left/right and
224                             // bottom left/right) during qpel refinement
225                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
226                    ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
227                    ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
228                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
229                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
230                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
231                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
232                    break;
233            }
234            return Reference;
235    }
236    
237    /* CHECK_CANDIATE FUNCTIONS START */
238    
239  static void  static void
240  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)
241  {  {
242          int32_t * const sad = data->temp;          int t, xc, yc;
 //      static int32_t sad[5];  
         int t;  
243          const uint8_t * Reference;          const uint8_t * Reference;
244            VECTOR * current;
245    
246          if (( x > data->max_dx) || ( x < data->min_dx)          if ( (x > data->max_dx) | (x < data->min_dx)
247                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  | (y > data->max_dy) | (y < data->min_dy) ) return;
248    
249          switch ( ((x&1)<<1) + (y&1) ) {          if (data->qpel_precision) { // x and y are in 1/4 precision
250                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;                  Reference = Interpolate16x16qpel(x, y, 0, data);
251                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  xc = x/2; yc = y/2; //for chroma sad
252                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;                  current = data->currentQMV;
253                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;          } else {
254                    Reference = GetReference(x, y, data);
255                    current = data->currentMV;
256                    xc = x; yc = y;
257          }          }
258            t = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
259    
260            data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
261    
262          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, sad+1);          data->temp[0] += (data->lambda16 * t * data->temp[0])>>10;
263            data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))>>10;
264    
265          t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          if (data->chroma) data->temp[0] += ChromaSAD((xc >> 1) + roundtab_79[xc & 0x3],
266          data->temp[0] += lambda_vec16[data->iQuant] * t;                                                                                                          (yc >> 1) + roundtab_79[yc & 0x3], data);
267          data->temp[1] += lambda_vec8[data->iQuant] * t;  
268            if (data->temp[0] < data->iMinSAD[0]) {
269                    data->iMinSAD[0] = data->temp[0];
270                    current[0].x = x; current[0].y = y;
271                    *dir = Direction; }
272    
273            if (data->temp[1] < data->iMinSAD[1]) {
274                    data->iMinSAD[1] = data->temp[1]; current[1].x = x; current[1].y= y; }
275            if (data->temp[2] < data->iMinSAD[2]) {
276                    data->iMinSAD[2] = data->temp[2]; current[2].x = x; current[2].y = y; }
277            if (data->temp[3] < data->iMinSAD[3]) {
278                    data->iMinSAD[3] = data->temp[3]; current[3].x = x; current[3].y = y; }
279            if (data->temp[4] < data->iMinSAD[4]) {
280                    data->iMinSAD[4] = data->temp[4]; current[4].x = x; current[4].y = y; }
281    
282    }
283    
284    static void
285    CheckCandidate32(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
286    {
287            uint32_t t;
288            const uint8_t * Reference;
289    
290            if ( (!(x&1) && x !=0) | (!(y&1) && y !=0) || //non-zero integer value
291                    (x > data->max_dx) | (x < data->min_dx)
292                    | (y > data->max_dy) | (y < data->min_dy) ) return;
293    
294            Reference = GetReference(x, y, data);
295            t = d_mv_bits(x, y, data->predMV, data->iFcode, 0, 1);
296    
297            data->temp[0] = sad32v_c(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
298    
299            data->temp[0] += (data->lambda16 * t * data->temp[0]) >> 10;
300            data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))>>10;
301    
302          if (data->temp[0] < data->iMinSAD[0]) {          if (data->temp[0] < data->iMinSAD[0]) {
303                  data->iMinSAD[0] = data->temp[0];                  data->iMinSAD[0] = data->temp[0];
# Line 118  Line 312 
312                  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; }
313          if (data->temp[4] < data->iMinSAD[4]) {          if (data->temp[4] < data->iMinSAD[4]) {
314                  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; }
   
315  }  }
316    
317  static void  static void
# Line 126  Line 319 
319  {  {
320          int32_t sad;          int32_t sad;
321          const uint8_t * Reference;          const uint8_t * Reference;
322            uint32_t t;
323            VECTOR * current;
324    
325          if (( x > data->max_dx) || ( x < data->min_dx)          if ( (x > data->max_dx) | ( x < data->min_dx)
326                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  | (y > data->max_dy) | (y < data->min_dy) ) return;
327    
328          switch ( ((x&1)<<1) + (y&1) )          if (data->rrv && (!(x&1) && x !=0) | (!(y&1) && y !=0) ) return; //non-zero even value
329          {  
330                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;          if (data->qpel_precision) { // x and y are in 1/4 precision
331                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  Reference = Interpolate16x16qpel(x, y, 0, data);
332                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;                  current = data->currentQMV;
333                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;          } else {
334                    Reference = GetReference(x, y, data);
335                    current = data->currentMV;
336          }          }
337            t = d_mv_bits(x, y, data->predMV, data->iFcode,
338                                            data->qpel^data->qpel_precision, data->rrv);
339    
340          sad = lambda_vec16[data->iQuant] *          sad = sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);
341                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          sad += (data->lambda16 * t * sad)>>10;
         sad += sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);  
342    
343          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
344                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
345                    current->x = x; current->y = y;
346                    *dir = Direction; }
347    }
348    
349    static void
350    CheckCandidate32I(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
351    {
352    // maximum speed - for P/B/I decision
353    
354            if ( (x > data->max_dx) | (x < data->min_dx)
355                    | (y > data->max_dy) | (y < data->min_dy) ) return;
356    
357            data->temp[0] = sad32v_c(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),
358                                                            data->iEdgedWidth, data->temp+1);
359    
360            if (data->temp[0] < *(data->iMinSAD)) {
361                    *(data->iMinSAD) = data->temp[0];
362                  data->currentMV[0].x = x; data->currentMV[0].y = y;                  data->currentMV[0].x = x; data->currentMV[0].y = y;
363                  *dir = Direction; }                  *dir = Direction; }
364            if (data->temp[1] < data->iMinSAD[1]) {
365                    data->iMinSAD[1] = data->temp[1]; data->currentMV[1].x = x; data->currentMV[1].y = y; }
366            if (data->temp[2] < data->iMinSAD[2]) {
367                    data->iMinSAD[2] = data->temp[2]; data->currentMV[2].x = x; data->currentMV[2].y = y; }
368            if (data->temp[3] < data->iMinSAD[3]) {
369                    data->iMinSAD[3] = data->temp[3]; data->currentMV[3].x = x; data->currentMV[3].y = y; }
370            if (data->temp[4] < data->iMinSAD[4]) {
371                    data->iMinSAD[4] = data->temp[4]; data->currentMV[4].x = x; data->currentMV[4].y = y; }
372    
373  }  }
374    
375  static void  static void
376  CheckCandidateInt(const int xf, const int yf, const int Direction, int * const dir, const SearchData * const data)  CheckCandidateInt(const int xf, const int yf, const int Direction, int * const dir, const SearchData * const data)
377  {  {
378          int32_t sad;          int32_t sad, xb, yb;
379          const int xb = data->currentMV[1].x;          uint32_t t;
         const int yb = data->currentMV[1].y;  
380          const uint8_t *ReferenceF, *ReferenceB;          const uint8_t *ReferenceF, *ReferenceB;
381            VECTOR *current;
382    
383          if (( xf > data->max_dx) || ( xf < data->min_dx)          if ( (xf > data->max_dx) | (xf < data->min_dx)
384                  || ( yf > data->max_dy) || (yf < data->min_dy)) return;                  | (yf > data->max_dy) | (yf < data->min_dy) ) return;
   
         switch ( ((xf&1)<<1) + (yf&1) ) {  
                 case 0 : ReferenceF = data->Ref + xf/2 + (yf/2)*(data->iEdgedWidth); break;  
                 case 1 : ReferenceF = data->RefV + xf/2 + ((yf-1)/2)*(data->iEdgedWidth); break;  
                 case 2 : ReferenceF = data->RefH + (xf-1)/2 + (yf/2)*(data->iEdgedWidth); break;  
                 default : ReferenceF = data->RefHV + (xf-1)/2 + ((yf-1)/2)*(data->iEdgedWidth); break;  
         }  
385    
386          switch ( ((xb&1)<<1) + (yb&1) ) {          if (!data->qpel_precision) {
387                  case 0 : ReferenceB = data->bRef + xb/2 + (yb/2)*(data->iEdgedWidth); break;                  ReferenceF = GetReference(xf, yf, data);
388                  case 1 : ReferenceB = data->bRefV + xb/2 + ((yb-1)/2)*(data->iEdgedWidth); break;                  xb = data->currentMV[1].x; yb = data->currentMV[1].y;
389                  case 2 : ReferenceB = data->bRefH + (xb-1)/2 + (yb/2)*(data->iEdgedWidth); break;                  ReferenceB = GetReferenceB(xb, yb, 1, data);
390                  default : ReferenceB = data->bRefHV + (xb-1)/2 + ((yb-1)/2)*(data->iEdgedWidth); break;                  current = data->currentMV;
391            } else {
392                    ReferenceF = Interpolate16x16qpel(xf, yf, 0, data);
393                    xb = data->currentQMV[1].x; yb = data->currentQMV[1].y;
394                    current = data->currentQMV;
395                    ReferenceB = Interpolate16x16qpel(xb, yb, 1, data);
396          }          }
397    
398          sad = lambda_vec16[data->iQuant] *          t = d_mv_bits(xf, yf, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0)
399                          ( d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode) +                   + d_mv_bits(xb, yb, data->bpredMV, data->iFcode, data->qpel^data->qpel_precision, 0);
                           d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode) );  
400    
401          sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
402            sad += (data->lambda16 * t * sad)>>10;
403    
404          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
405                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
406                  data->currentMV->x = xf; data->currentMV->y = yf;                  current->x = xf; current->y = yf;
407                  *dir = Direction; }                  *dir = Direction; }
408  }  }
409    
410  static void  static void
411  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)
412  {  {
413          int32_t sad;          int32_t sad = 0;
414          int k;          uint32_t k;
415          const uint8_t *ReferenceF;          const uint8_t *ReferenceF;
416          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
417          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
418    
419          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;          if (( x > 31) | ( x < -32) | ( y > 31) | (y < -32)) return;
   
         sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);  
420    
421          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
422                  mvs.x = data->directmvF[k].x + x;                  mvs.x = data->directmvF[k].x + x;
# Line 214  Line 434 
434                          || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )                          || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )
435                          || ( 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;
436    
                 switch ( ((mvs.x&1)<<1) + (mvs.y&1) ) {  
                         case 0 : ReferenceF = data->Ref + mvs.x/2 + (mvs.y/2)*(data->iEdgedWidth); break;  
                         case 1 : ReferenceF = data->RefV + mvs.x/2 + ((mvs.y-1)/2)*(data->iEdgedWidth); break;  
                         case 2 : ReferenceF = data->RefH + (mvs.x-1)/2 + (mvs.y/2)*(data->iEdgedWidth); break;  
                         default : ReferenceF = data->RefHV + (mvs.x-1)/2 + ((mvs.y-1)/2)*(data->iEdgedWidth); break;  
                 }  
437    
438                  switch ( ((b_mvs.x&1)<<1) + (b_mvs.y&1) ) {                  mvs.x *= 2 - data->qpel; mvs.y *= 2 - data->qpel;
439                          case 0 : ReferenceB = data->bRef + b_mvs.x/2 + (b_mvs.y/2)*(data->iEdgedWidth); break;                  b_mvs.x *= 2 - data->qpel; b_mvs.y *= 2 - data->qpel; //we move to qpel precision anyway
440                          case 1 : ReferenceB = data->bRefV + b_mvs.x/2 + ((b_mvs.y-1)/2)*(data->iEdgedWidth); break;  
441                          case 2 : ReferenceB = data->bRefH + (b_mvs.x-1)/2 + (b_mvs.y/2)*(data->iEdgedWidth); break;                  ReferenceF = Interpolate8x8qpel(mvs.x, mvs.y, k, 0, data);
442                          default : ReferenceB = data->bRefHV + (b_mvs.x-1)/2 + ((b_mvs.y-1)/2)*(data->iEdgedWidth); break;                  ReferenceB = Interpolate8x8qpel(b_mvs.x, b_mvs.y, k, 1, data);
                 }  
443    
444                  sad += sad8bi(data->Cur + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),                  sad += sad8bi(data->Cur + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
445                                                  ReferenceF + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),                                                  ReferenceF, ReferenceB, data->iEdgedWidth);
                                                 ReferenceB + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),  
                                                 data->iEdgedWidth);  
446                  if (sad > *(data->iMinSAD)) return;                  if (sad > *(data->iMinSAD)) return;
447          }          }
448    
449            sad += (data->lambda16 * d_mv_bits(x, y, zeroMV, 1, 0, 0) * sad)>>10;
450    
451          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
452                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
453                  data->currentMV->x = x; data->currentMV->y = y;                  data->currentMV->x = x; data->currentMV->y = y;
# Line 249  Line 462 
462          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
463          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
464    
465          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);  
466    
467          mvs.x = data->directmvF[0].x + x;          mvs.x = data->directmvF[0].x + x;
468          b_mvs.x = ((x == 0) ?          b_mvs.x = ((x == 0) ?
# Line 268  Line 479 
479                  || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )                  || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )
480                  || ( 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;
481    
482          switch ( ((mvs.x&1)<<1) + (mvs.y&1) ) {          mvs.x *= 2 - data->qpel; mvs.y *= 2 - data->qpel;
483                  case 0 : ReferenceF = data->Ref + mvs.x/2 + (mvs.y/2)*(data->iEdgedWidth); break;          b_mvs.x *= 2 - data->qpel; b_mvs.y *= 2 - data->qpel; //we move to qpel precision anyway
                 case 1 : ReferenceF = data->RefV + mvs.x/2 + ((mvs.y-1)/2)*(data->iEdgedWidth); break;  
                 case 2 : ReferenceF = data->RefH + (mvs.x-1)/2 + (mvs.y/2)*(data->iEdgedWidth); break;  
                 default : ReferenceF = data->RefHV + (mvs.x-1)/2 + ((mvs.y-1)/2)*(data->iEdgedWidth); break;  
         }  
484    
485          switch ( ((b_mvs.x&1)<<1) + (b_mvs.y&1) ) {          ReferenceF = Interpolate16x16qpel(mvs.x, mvs.y, 0, data);
486                  case 0 : ReferenceB = data->bRef + b_mvs.x/2 + (b_mvs.y/2)*(data->iEdgedWidth); break;          ReferenceB = Interpolate16x16qpel(b_mvs.x, b_mvs.y, 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;  
         }  
487    
488          sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
489            sad += (data->lambda16 * d_mv_bits(x, y, zeroMV, 1, 0, 0) * sad)>>10;
490    
491          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
492                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 293  Line 497 
497  static void  static void
498  CheckCandidate8(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidate8(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
499  {  {
500          int32_t sad;          int32_t sad; uint32_t t;
501          const uint8_t * Reference;          const uint8_t * Reference;
502    
503          if (( x > data->max_dx) || ( x < data->min_dx)          if ( (x > data->max_dx) | (x < data->min_dx)
504                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  | (y > data->max_dy) | (y < data->min_dy) ) return;
505    
506          switch ( ((x&1)<<1) + (y&1) )          if (data->qpel) Reference = Interpolate16x16qpel(x, y, 0, data);
507          {          else Reference = GetReference(x, y, data);
                 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;  
         }  
508    
509          sad = sad8(data->Cur, Reference, data->iEdgedWidth);          sad = sad8(data->Cur, Reference, data->iEdgedWidth);
510          sad += lambda_vec8[data->iQuant] * d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          t = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel && !data->qpel_precision, 0);
511    
512            sad += (data->lambda8 * t * (sad+NEIGH_8X8_BIAS))>>10;
513    
514          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
515                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 316  Line 517 
517                  *dir = Direction; }                  *dir = Direction; }
518  }  }
519    
520  /* CHACK_CANDIATE FUNCTIONS END */  /* CHECK_CANDIATE FUNCTIONS END */
521    
522  /* MAINSEARCH FUNCTIONS START */  /* MAINSEARCH FUNCTIONS START */
523    
# Line 328  Line 529 
529    
530                  int iDirection;                  int iDirection;
531    
532                  do {          for(;;) { //forever
533                          iDirection = 0;                          iDirection = 0;
534                          if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);                          if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);
535                          if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);                          if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);
# Line 337  Line 538 
538    
539                          /* now we're doing diagonal checks near our candidate */                          /* now we're doing diagonal checks near our candidate */
540    
541                          if (iDirection) {               //checking if anything found                  if (iDirection) {               //if anything found
542                                  bDirection = iDirection;                                  bDirection = iDirection;
543                                  iDirection = 0;                                  iDirection = 0;
544                                  x = data->currentMV->x; y = data->currentMV->y;                                  x = data->currentMV->x; y = data->currentMV->y;
# Line 346  Line 547 
547                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);
548                                  } else {                        // what remains here is up or down                                  } else {                        // what remains here is up or down
549                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);
550                                          CHECK_CANDIDATE(x - iDiamondSize, y, 1); }                                  CHECK_CANDIDATE(x - iDiamondSize, y, 1);
551                            }
552    
553                                  if (iDirection) {                                  if (iDirection) {
554                                          bDirection += iDirection;                                          bDirection += iDirection;
555                                          x = data->currentMV->x; y = data->currentMV->y; }                                  x = data->currentMV->x; y = data->currentMV->y;
556                            }
557                          } else {                                //about to quit, eh? not so fast....                          } else {                                //about to quit, eh? not so fast....
558                                  switch (bDirection) {                                  switch (bDirection) {
559                                  case 2:                                  case 2:
# Line 401  Line 604 
604                                  x = data->currentMV->x; y = data->currentMV->y;                                  x = data->currentMV->x; y = data->currentMV->y;
605                          }                          }
606                  }                  }
                 while (1);                              //forever  
607  }  }
608    
609  static void  static void
# Line 451  Line 653 
653                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);
654                                  } else {                        // what remains here is up or down                                  } else {                        // what remains here is up or down
655                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);
656                                          CHECK_CANDIDATE(x - iDiamondSize, y, 1); }                                  CHECK_CANDIDATE(x - iDiamondSize, y, 1);
657                            }
658                                  bDirection += iDirection;                                  bDirection += iDirection;
659                                  x = data->currentMV->x; y = data->currentMV->y;                                  x = data->currentMV->x; y = data->currentMV->y;
660                          }                          }
# Line 462  Line 664 
664    
665  /* MAINSEARCH FUNCTIONS END */  /* MAINSEARCH FUNCTIONS END */
666    
 /* HALFPELREFINE COULD BE A MAINSEARCH FUNCTION, BUT THERE IS NO NEED FOR IT */  
   
667  static void  static void
668  HalfpelRefine(const SearchData * const data)  SubpelRefine(const SearchData * const data)
669  {  {
670  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a half-pel or q-pel refinement */
671            const VECTOR centerMV = data->qpel_precision ? *data->currentQMV : *data->currentMV;
672          VECTOR backupMV = *(data->currentMV);          int iDirection; //only needed because macro expects it
673          int iDirection; //not needed  
674            CHECK_CANDIDATE(centerMV.x, centerMV.y - 1, 0);
675          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);          CHECK_CANDIDATE(centerMV.x + 1, centerMV.y - 1, 0);
676          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);          CHECK_CANDIDATE(centerMV.x + 1, centerMV.y, 0);
677          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);          CHECK_CANDIDATE(centerMV.x + 1, centerMV.y + 1, 0);
678          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y + 1, 0);          CHECK_CANDIDATE(centerMV.x, centerMV.y + 1, 0);
679            CHECK_CANDIDATE(centerMV.x - 1, centerMV.y + 1, 0);
680          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y, 0);          CHECK_CANDIDATE(centerMV.x - 1, centerMV.y, 0);
681          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);  
682  }  }
683    
684  static __inline int  static __inline int
685  SkipDecisionP(const IMAGE * current, const IMAGE * reference,  SkipDecisionP(const IMAGE * current, const IMAGE * reference,
686                                                          const int x, const int y,                                                          const int x, const int y,
687                                                          const uint32_t iEdgedWidth, const uint32_t iQuant)                                                          const uint32_t stride, const uint32_t iQuant, int rrv)
688    
689  {  {
690  /*      keep repeating checks for all b-frames before this P frame,          if(!rrv) {
691          to make sure that SKIP is possible (todo)                  uint32_t sadC = sad8(current->u + x*8 + y*stride*8,
692          how: if skip is not possible set sad00 to a very high value */                                                  reference->u + x*8 + y*stride*8, stride);
   
         uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,  
                                         reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);  
693          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
694          sadC += sad8(current->v + x*8 + y*(iEdgedWidth/2)*8,                  sadC += sad8(current->v + (x + y*stride)*8,
695                                          reference->v + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                                  reference->v + (x + y*stride)*8, stride);
696          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
697                    return 1;
698    
699            } else {
700                    uint32_t sadC = sad16(current->u + x*16 + y*stride*16,
701                                                    reference->u + x*16 + y*stride*16, stride, 256*4096);
702                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP*4) return 0;
703                    sadC += sad16(current->v + (x + y*stride)*16,
704                                                    reference->v + (x + y*stride)*16, stride, 256*4096);
705                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP*4) return 0;
706          return 1;          return 1;
707  }  }
708    }
709    
710  static __inline void  static __inline void
711  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)
712  {  {
713          pMB->mode = MODE_NOT_CODED;          pMB->mode = MODE_NOT_CODED;
714          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = pMB->mv16.x = 0;          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = zeroMV;
715          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = pMB->mv16.y = 0;          pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] = pMB->qmvs[3] = zeroMV;
716          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;
717  }  }
718    
# Line 526  Line 729 
729          const IMAGE *const pCurrent = &current->image;          const IMAGE *const pCurrent = &current->image;
730          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
731    
732          const VECTOR zeroMV = { 0, 0 };          uint32_t mb_width = pParam->mb_width;
733            uint32_t mb_height = pParam->mb_height;
734            const uint32_t iEdgedWidth = pParam->edged_width;
735    
736          uint32_t x, y;          uint32_t x, y;
737          uint32_t iIntra = 0;          uint32_t iIntra = 0;
738          int32_t InterBias;          int32_t InterBias, quant = current->quant, sad00;
739    
740          if (sadInit) (*sadInit) ();          // some pre-initialized thingies for SearchP
741            int32_t temp[8];
742            VECTOR currentMV[5];
743            VECTOR currentQMV[5];
744            int32_t iMinSAD[5];
745            SearchData Data;
746            memset(&Data, 0, sizeof(SearchData));
747            Data.iEdgedWidth = iEdgedWidth;
748            Data.currentMV = currentMV;
749            Data.currentQMV = currentQMV;
750            Data.iMinSAD = iMinSAD;
751            Data.temp = temp;
752            Data.iFcode = current->fcode;
753            Data.rounding = pParam->m_rounding_type;
754            Data.qpel = pParam->m_quarterpel;
755            Data.chroma = current->global_flags & XVID_ME_COLOUR;
756            Data.rrv = current->global_flags & XVID_REDUCED;
757    
758            if ((current->global_flags & XVID_REDUCED)) {
759                    mb_width = (pParam->width + 31) / 32;
760                    mb_height = (pParam->height + 31) / 32;
761                    Data.qpel = Data.chroma = 0;
762            }
763    
764          for (y = 0; y < pParam->mb_height; y++) {          Data.RefQ = pRefV->u; // a good place, also used in MC (for similar purpose)
765                  for (x = 0; x < pParam->mb_width; x++)  {          if (sadInit) (*sadInit) ();
766    
767            for (y = 0; y < mb_height; y++) {
768                    for (x = 0; x < mb_width; x++)  {
769                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
770                          int32_t sad00 =  pMB->sad16  
771                                  = sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,                          if (!Data.rrv) pMB->sad16 =
772                                                          pRef->y + (x + y * pParam->edged_width) * 16,                                  sad16v(pCurrent->y + (x + y * iEdgedWidth) * 16,
773                                                            pRef->y + (x + y * iEdgedWidth) * 16,
774                                                          pParam->edged_width, pMB->sad8 );                                                          pParam->edged_width, pMB->sad8 );
775    
776                            else pMB->sad16 =
777                                    sad32v_c(pCurrent->y + (x + y * iEdgedWidth) * 32,
778                                                            pRef->y + (x + y * iEdgedWidth) * 32,
779                                                            pParam->edged_width, pMB->sad8 );
780    
781                            if (Data.chroma) {
782                                    Data.temp[7] = sad8(pCurrent->u + x*8 + y*(iEdgedWidth/2)*8,
783                                                                            pRef->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2)
784                                                                    + sad8(pCurrent->v + (x + y*(iEdgedWidth/2))*8,
785                                                                            pRef->v + (x + y*(iEdgedWidth/2))*8, iEdgedWidth/2);
786                                    pMB->sad16 += Data.temp[7];
787                            }
788    
789                            sad00 = pMB->sad16;
790    
791                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
792                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
793                                  pMB->quant = current->quant; }                          } else {
794                                    if (pMB->dquant != NO_CHANGE) {
795                                            quant += DQtab[pMB->dquant];
796                                            if (quant > 31) quant = 31;
797                                            else if (quant < 1) quant = 1;
798                                    }
799                            }
800                            pMB->quant = current->quant;
801    
802  //initial skip decision  //initial skip decision
803    /* no early skip for GMC (global vector = skip vector is unknown!)      */
804                          if ((pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)                          if (current->coding_type == P_VOP)      { /* no fast SKIP for S(GMC)-VOPs */
805                                  && (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) ) {                                  if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * INITIAL_SKIP_THRESH * (Data.rrv ? 4:1) )
806                                  if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {                                          if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, iEdgedWidth/2, pMB->quant, Data.rrv)) {
807                                                  SkipMacroblockP(pMB, sad00);                                                  SkipMacroblockP(pMB, sad00);
808                                                  continue;                                                  continue;
809                                  }                                  }
810                          } else sad00 = 256*4096; // skip not allowed - for final skip decision                          }
811    
812                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchP(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
813                                                  y, current->motion_flags, pMB->quant,                                                  y, current->motion_flags, pMB->quant,
814                                                  current->fcode, pParam, pMBs, reference->mbs,                                                  &Data, pParam, pMBs, reference->mbs,
815                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
816    
817  /* final skip decision, a.k.a. "the vector you found, really that good?" */  /* final skip decision, a.k.a. "the vector you found, really that good?" */
818                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)                          if (current->coding_type == P_VOP)      {
819                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)                                  if ( (pMB->dquant == NO_CHANGE) && (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)
820                                  { SkipMacroblockP(pMB, sad00); continue; }                                          && ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH * (Data.rrv ? 4:1)) )
821                                            if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, iEdgedWidth/2, pMB->quant, Data.rrv)) {
822                                                    SkipMacroblockP(pMB, sad00);
823                                                    continue;
824                                            }
825                            }
826    
827  /* finally, intra decision */  /* finally, intra decision */
828    
829                          InterBias = MV16_INTER_BIAS;                          InterBias = MV16_INTER_BIAS;
830                          if (pMB->quant > 8)  InterBias += 50 * (pMB->quant - 8); // to make high quants work                          if (pMB->quant > 8) InterBias += 100 * (pMB->quant - 8); // to make high quants work
831                          if (y != 0)                          if (y != 0)
832                                  if ((pMB - pParam->mb_width)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - pParam->mb_width)->mode == MODE_INTRA ) InterBias -= 80;
833                          if (x != 0)                          if (x != 0)
834                                  if ((pMB - 1)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - 1)->mode == MODE_INTRA ) InterBias -= 80;
835    
836                          if (InterBias < pMB->sad16)  {                          if (Data.chroma) InterBias += 50; // to compensate bigger SAD
837                                  const int32_t deviation =                          if (Data.rrv) InterBias *= 4;
                                         dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,  
                                                   pParam->edged_width);  
838    
839                            if (InterBias < pMB->sad16) {
840                                    int32_t deviation;
841                                    if (!Data.rrv)
842                                            deviation = dev16(pCurrent->y + (x + y * iEdgedWidth) * 16, iEdgedWidth);
843                                    else {
844                                            deviation = dev16(pCurrent->y + (x + y * iEdgedWidth) * 32, iEdgedWidth)
845                                                    + dev16(pCurrent->y + (x + y * iEdgedWidth) * 32 + 16, iEdgedWidth)
846                                                    + dev16(pCurrent->y + (x + y * iEdgedWidth) * 32 + 16 * iEdgedWidth, iEdgedWidth)
847                                                    + dev16(pCurrent->y + (x + y * iEdgedWidth) * 32 + 16 * (iEdgedWidth+1), iEdgedWidth);
848                                    }
849                                  if (deviation < (pMB->sad16 - InterBias)) {                                  if (deviation < (pMB->sad16 - InterBias)) {
850                                          if (++iIntra >= iLimit) return 1;                                          if (++iIntra >= iLimit) return 1;
851                                            SkipMacroblockP(pMB, 0); //same thing
852                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
                                         pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =  
                                                 pMB->mvs[3] = zeroMV;  
                                         pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =  
                                                 pMB->sad8[3] = 0;  
853                                  }                                  }
854                          }                          }
855                  }                  }
856          }          }
857    
858            if (current->coding_type == S_VOP)      /* first GMC step only for S(GMC)-VOPs */
859                    current->GMC_MV = GlobalMotionEst( pMBs, pParam, current->fcode );
860            else
861                    current->GMC_MV = zeroMV;
862    
863          return 0;          return 0;
864  }  }
865    
866    
 #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  
   
867  static __inline int  static __inline int
868  make_mask(const VECTOR * const pmv, const int i)  make_mask(const VECTOR * const pmv, const int i)
869  {  {
870          int mask = 0xFF, j;          int mask = 255, j;
871          for (j = 0; j < i; j++) {          for (j = 0; j < i; j++) {
872                  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
873                  if (pmv[i].x == pmv[j].x) {                  if (pmv[i].x == pmv[j].x) {
874                          if (pmv[i].y == pmv[j].y + iDiamondSize) { mask &= ~4; continue; }                          if (pmv[i].y == pmv[j].y + iDiamondSize) mask &= ~4;
875                          if (pmv[i].y == pmv[j].y - iDiamondSize) { mask &= ~8; continue; }                          else if (pmv[i].y == pmv[j].y - iDiamondSize) mask &= ~8;
876                  } else                  } else
877                          if (pmv[i].y == pmv[j].y) {                          if (pmv[i].y == pmv[j].y) {
878                                  if (pmv[i].x == pmv[j].x + iDiamondSize) { mask &= ~1; continue; }                                  if (pmv[i].x == pmv[j].x + iDiamondSize) mask &= ~1;
879                                  if (pmv[i].x == pmv[j].x - iDiamondSize) { mask &= ~2; continue; }                                  else if (pmv[i].x == pmv[j].x - iDiamondSize) mask &= ~2;
880                          }                          }
881          }          }
882          return mask;          return mask;
883  }  }
884    
885  static __inline void  static __inline void
886  PreparePredictionsP(VECTOR * const pmv, int x, int y, const int iWcount,  PreparePredictionsP(VECTOR * const pmv, int x, int y, int iWcount,
887                          const int iHcount, const MACROBLOCK * const prevMB)                          int iHcount, const MACROBLOCK * const prevMB, int rrv)
888  {  {
889    
890  //this function depends on get_pmvdata which means that it sucks. It should get the predictions by itself  //this function depends on get_pmvdata which means that it sucks. It should get the predictions by itself
891            if (rrv) { iWcount /= 2; iHcount /= 2; }
892    
893          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour          if ( (y != 0) && (x < (iWcount-1)) ) {          // [5] top-right neighbour
894                  pmv[5].x = EVEN(pmv[3].x);                  pmv[5].x = EVEN(pmv[3].x);
895                  pmv[5].y = EVEN(pmv[3].y); }                  pmv[5].y = EVEN(pmv[3].y);
896          else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
897    
898          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
899          else pmv[3].x = pmv[3].y = 0;          else pmv[3].x = pmv[3].y = 0;
# Line 642  Line 909 
909          pmv[2].x = EVEN(prevMB->mvs[0].x); // [2] is last frame          pmv[2].x = EVEN(prevMB->mvs[0].x); // [2] is last frame
910          pmv[2].y = EVEN(prevMB->mvs[0].y);          pmv[2].y = EVEN(prevMB->mvs[0].y);
911    
912          if ((x != iWcount-1) && (y != iHcount-1)) {          if ((x < iWcount-1) && (y < iHcount-1)) {
913                  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
914                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y); }                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
915          else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
916    
917            if (rrv) {
918                    int i;
919                    for (i = 0; i < 7; i++) {
920                            pmv[i].x = RRV_MV_SCALEUP(pmv[i].x);
921                            pmv[i].y = RRV_MV_SCALEUP(pmv[i].y);
922                    }
923            }
924  }  }
925    
926  static void  static void
927  SearchP(const uint8_t * const pRef,  SearchP(const IMAGE * const pRef,
928                  const uint8_t * const pRefH,                  const uint8_t * const pRefH,
929                  const uint8_t * const pRefV,                  const uint8_t * const pRefV,
930                  const uint8_t * const pRefHV,                  const uint8_t * const pRefHV,
# Line 658  Line 933 
933                  const int y,                  const int y,
934                  const uint32_t MotionFlags,                  const uint32_t MotionFlags,
935                  const uint32_t iQuant,                  const uint32_t iQuant,
936                  const uint32_t iFcode,                  SearchData * const Data,
937                  const MBParam * const pParam,                  const MBParam * const pParam,
938                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
939                  const MACROBLOCK * const prevMBs,                  const MACROBLOCK * const prevMBs,
# Line 666  Line 941 
941                  MACROBLOCK * const pMB)                  MACROBLOCK * const pMB)
942  {  {
943    
         const int32_t iEdgedWidth = pParam->edged_width;  
   
944          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
945          int32_t temp[5];          VECTOR pmv[7];
         VECTOR currentMV[5], pmv[7];  
         int32_t psad[4], iMinSAD[5];  
         MainSearchFunc * MainSearchPtr;  
         SearchData Data;  
946    
947          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, psad);  //has to be changed to get_pmv(2)()          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
948          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,                                                  pParam->width, pParam->height, Data->iFcode - Data->qpel, 0, Data->rrv);
                                 pParam->width, pParam->height, iFcode);  
949    
950          Data.predMV = pmv[0];          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);
         Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
         Data.iEdgedWidth = iEdgedWidth;  
         Data.currentMV = currentMV;  
         Data.iMinSAD = iMinSAD;  
         Data.Ref = pRef + (x + iEdgedWidth*y)*16;  
         Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;  
         Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;  
         Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;  
         Data.temp = temp;  
951    
952          Data.iQuant = iQuant;          Data->temp[5] = Data->temp[6] = 0; // chroma-sad cache
953          Data.iFcode = iFcode;          i = Data->rrv ? 2 : 1;
954            Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16*i;
955          if (!(MotionFlags & PMV_HALFPEL16)) {          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
956                  Data.min_dx = EVEN(Data.min_dx);          Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
957                  Data.max_dx = EVEN(Data.max_dx);  
958                  Data.min_dy = EVEN(Data.min_dy);          Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16*i;
959                  Data.max_dy = EVEN(Data.max_dy); }          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16*i;
960            Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16*i;
961          for(i = 0;  i < 5; i++) currentMV[i].x = currentMV[i].y = 0;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16*i;
962            Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
963          i = d_mv_bits(pmv[0].x, pmv[0].y, iFcode);          Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
964    
965          iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;          Data->lambda16 = lambda_vec16[iQuant];
966          iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;          Data->lambda8 = lambda_vec8[iQuant];
967          iMinSAD[2] = pMB->sad8[1];          Data->qpel_precision = 0;
         iMinSAD[3] = pMB->sad8[2];  
         iMinSAD[4] = pMB->sad8[3];  
968    
969          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
970    
971          if ((x == 0) && (y == 0)) threshA = 512;          for(i = 0; i < 5; i++)
972          else {                  Data->currentMV[i].x = Data->currentMV[i].y = 0;
973                  threshA = psad[0] + 20;  
974            if (Data->qpel) Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
975            else Data->predMV = pmv[0];
976    
977            i = d_mv_bits(0, 0, Data->predMV, Data->iFcode, 0, 0);
978            Data->iMinSAD[0] = pMB->sad16 + ((Data->lambda16 * i * pMB->sad16)>>10);
979            Data->iMinSAD[1] = pMB->sad8[0] + ((Data->lambda8 * i * (pMB->sad8[0]+NEIGH_8X8_BIAS)) >> 10);
980            Data->iMinSAD[2] = pMB->sad8[1];
981            Data->iMinSAD[3] = pMB->sad8[2];
982            Data->iMinSAD[4] = pMB->sad8[3];
983    
984            if (x | y) {
985                    threshA = Data->temp[0]; // that's when we keep this SAD atm
986                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
987                  if (threshA > 1024) threshA = 1024; }                  else if (threshA > 1024) threshA = 1024;
988            } else threshA = 512;
989    
990          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,
991                                          prevMBs + x + y * pParam->mb_width);                                          prevMBs + x + y * pParam->mb_width, Data->rrv);
992    
993          if (inter4v) CheckCandidate = CheckCandidate16;          if (!Data->rrv) {
994          else CheckCandidate = CheckCandidate16no4v;                  if (inter4v | Data->chroma) CheckCandidate = CheckCandidate16;
995                            else CheckCandidate = CheckCandidate16no4v; //for extra speed
996            } else CheckCandidate = CheckCandidate32;
997    
998  /* main loop. checking all predictions */  /* main loop. checking all predictions (but first, which is 0,0 and has been checked in MotionEstimation())*/
999    
1000          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
1001                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1002                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  (*CheckCandidate)(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1003                  if (iMinSAD[0] < threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1004          }          }
1005    
1006          if ((iMinSAD[0] <= threshA) ||          if ((Data->iMinSAD[0] <= threshA) ||
1007                          (MVequal(currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
1008                          (iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {                          (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16)))
1009                  inter4v = 0;                  inter4v = 0;
1010                  if (MotionFlags & PMV_QUICKSTOP16) goto PMVfast16_Terminate_without_Refine;          else {
                 if (MotionFlags & PMV_EARLYSTOP16) {  
                         CheckCandidate = CheckCandidate16no4v; // I sure hope it's faster  
                         goto PMVfast16_Terminate_with_Refine;  
                 }  
         }  
1011    
1012          if (MotionFlags & PMV_USESQUARES16)                  MainSearchFunc * MainSearchPtr;
1013                  MainSearchPtr = SquareSearch;                  if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
1014          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
                 MainSearchPtr = AdvDiamondSearch;  
1015                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1016    
1017          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, iDirection);                  (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1018    
1019  /* extended search, diamond starting in 0,0 and in prediction.  /* extended search, diamond starting in 0,0 and in prediction.
1020          note that this search is/might be done in halfpel positions,          note that this search is/might be done in halfpel positions,
# Line 756  Line 1022 
1022    
1023          if (MotionFlags & PMV_EXTSEARCH16) {          if (MotionFlags & PMV_EXTSEARCH16) {
1024                  int32_t bSAD;                  int32_t bSAD;
1025                  VECTOR startMV = Data.predMV, backupMV = currentMV[0];                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
1026                            if (Data->rrv) {
1027                                    startMV.x = RRV_MV_SCALEUP(startMV.x);
1028                                    startMV.y = RRV_MV_SCALEUP(startMV.y);
1029                            } else
1030                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?
1031                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);
1032                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1033                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1034    
1035                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1036                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1037                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1038                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1039                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1040                  }                  }
1041    
1042                  backupMV = currentMV[0];                          backupMV = Data->currentMV[0];
1043                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;                          if (MotionFlags & PMV_HALFPELREFINE16 && !Data->rrv) startMV.x = startMV.y = 1;
1044                  else startMV.x = startMV.y = 0;                  else startMV.x = startMV.y = 0;
1045                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1046                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1047    
1048                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1049                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1050                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1051                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1052                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1053                  }                  }
1054          }          }
1055            }
1056    
1057            if (MotionFlags & PMV_HALFPELREFINE16) SubpelRefine(Data);
1058    
1059            for(i = 0; i < 5; i++) {
1060                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1061                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1062            }
1063    
1064            if (Data->qpel && MotionFlags & PMV_QUARTERPELREFINE16) {
1065                    Data->qpel_precision = 1;
1066                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1067                                    pParam->width, pParam->height, Data->iFcode, 1, 0);
1068    
1069                    SubpelRefine(Data);
1070            }
1071    
1072            if (Data->iMinSAD[0] < (int32_t)iQuant * 30) inter4v = 0;
1073            if (inter4v) {
1074                    SearchData Data8;
1075                    memcpy(&Data8, Data, sizeof(SearchData)); //quick copy of common data
1076    
1077  PMVfast16_Terminate_with_Refine:                  Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1078                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1079                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1080                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1081    
1082          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);                  if (Data->chroma) {
1083                            int sumx = 0, sumy = 0;
1084                            const int div = 1 + Data->qpel;
1085                            const VECTOR * const mv = Data->qpel ? pMB->qmvs : pMB->mvs;
1086    
1087  PMVfast16_Terminate_without_Refine:                          for (i = 0; i < 4; i++) {
1088                                    sumx += mv[i].x / div;
1089                                    sumy += mv[i].y / div;
1090                            }
1091    
1092          if (inter4v)                          Data->iMinSAD[1] += ChromaSAD(  (sumx >> 3) + roundtab_76[sumx & 0xf],
1093                  for(i = 0; i < 4; i++)                                                                                          (sumy >> 3) + roundtab_76[sumy & 0xf], Data);
1094                          Search8(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                  }
1095            }
1096    
1097            if (Data->rrv) {
1098                            Data->currentMV[0].x = RRV_MV_SCALEDOWN(Data->currentMV[0].x);
1099                            Data->currentMV[0].y = RRV_MV_SCALEDOWN(Data->currentMV[0].y);
1100            }
1101    
1102          if (!(inter4v) ||          if (!(inter4v) ||
1103                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
1104                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1105  // INTER MODE  // INTER MODE
1106                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1107                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1108                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = Data->iMinSAD[0];
1109    
1110                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  if(Data->qpel) {
1111                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->qmvs[0] = pMB->qmvs[1]
1112                                    = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1113                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predMV.x;
1114                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predMV.y;
1115                    } else {
1116                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1117                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1118                    }
1119          } else {          } else {
1120  // INTER4V MODE; all other things are already set in Search8  // INTER4V MODE; all other things are already set in Search8
1121                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1122                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1123                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1124          }          }
   
1125  }  }
1126    
1127  static void  static void
# Line 820  Line 1131 
1131                  const MBParam * const pParam,                  const MBParam * const pParam,
1132                  MACROBLOCK * const pMB,                  MACROBLOCK * const pMB,
1133                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
1134                  const int block)                  const int block,
1135                    SearchData * const Data)
1136  {  {
1137          SearchData Data;          int i = 0;
1138            Data->iMinSAD = OldData->iMinSAD + 1 + block;
1139            Data->currentMV = OldData->currentMV + 1 + block;
1140            Data->currentQMV = OldData->currentQMV + 1 + block;
1141    
1142            if(Data->qpel) {
1143                    Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2, y/2, block);
1144                    if (block != 0) i = d_mv_bits(  Data->currentQMV->x, Data->currentQMV->y,
1145                                                                                    Data->predMV, Data->iFcode, 0, 0);
1146            } else {
1147                    Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2, y/2, block);
1148                    if (block != 0) i = d_mv_bits(  Data->currentMV->x, Data->currentMV->y,
1149                                                                                    Data->predMV, Data->iFcode, 0, Data->rrv);
1150            }
1151    
1152          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          *(Data->iMinSAD) += (Data->lambda8 * i * (*Data->iMinSAD + NEIGH_8X8_BIAS))>>10;
         Data.iMinSAD = OldData->iMinSAD + 1 + block;  
         Data.currentMV = OldData->currentMV+1+block;  
         Data.iFcode = OldData->iFcode;  
         Data.iQuant = OldData->iQuant;  
   
         if (block != 0)  
                 *(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));  
1153    
1154                  Data.iEdgedWidth = pParam->edged_width;          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8|PMV_QUARTERPELREFINE8)) {
1155                    if (Data->rrv) i = 2; else i = 1;
1156    
1157                  Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Ref = OldData->Ref + i * 8 * ((block&1) + Data->iEdgedWidth*(block>>1));
1158                    Data->RefH = OldData->RefH + i * 8 * ((block&1) + Data->iEdgedWidth*(block>>1));
1159                    Data->RefV = OldData->RefV + i * 8 * ((block&1) + Data->iEdgedWidth*(block>>1));
1160                    Data->RefHV = OldData->RefHV + i * 8 * ((block&1) + Data->iEdgedWidth*(block>>1));
1161    
1162                  get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,                  Data->Cur = OldData->Cur + i * 8 * ((block&1) + Data->iEdgedWidth*(block>>1));
1163                                  pParam->width, pParam->height, OldData->iFcode);                  Data->qpel_precision = 0;
1164    
1165                  CheckCandidate = CheckCandidate8;                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1166                                            pParam->width, pParam->height, Data->iFcode - Data->qpel, 0, Data->rrv);
1167    
1168                    if (!Data->rrv) CheckCandidate = CheckCandidate8;
1169                    else CheckCandidate = CheckCandidate16no4v;
1170    
1171                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & PMV_EXTSEARCH8) {
1172                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1173    
1174                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1175                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1176                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1177                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1178    
1179                          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);     }                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1180    
1181                            if(*(Data->iMinSAD) < temp_sad) {
1182                                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1183                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1184                            }
1185                    }
1186    
1187                    if (MotionFlags & PMV_HALFPELREFINE8) {
1188                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1189    
1190                            SubpelRefine(Data); // perform halfpel refine of current best vector
1191    
1192                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                          if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1193                                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1194                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1195                            }
1196          }          }
1197    
1198          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;                  if (Data->qpel && MotionFlags & PMV_QUARTERPELREFINE8) {
1199          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;                                  Data->qpel_precision = 1;
1200          pMB->mvs[block] = *(Data.currentMV);                                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1201          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                                          pParam->width, pParam->height, Data->iFcode, 1, 0);
1202                                    SubpelRefine(Data);
1203                    }
1204  }  }
1205    
1206  /* B-frames code starts here */          if (Data->rrv) {
1207                            Data->currentMV->x = RRV_MV_SCALEDOWN(Data->currentMV->x);
1208                            Data->currentMV->y = RRV_MV_SCALEDOWN(Data->currentMV->y);
1209            }
1210    
1211            if(Data->qpel) {
1212                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predMV.x;
1213                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predMV.y;
1214                    pMB->qmvs[block] = *Data->currentQMV;
1215            } else {
1216                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1217                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1218            }
1219    
1220            pMB->mvs[block] = *Data->currentMV;
1221            pMB->sad8[block] = 4 * *Data->iMinSAD;
1222    }
1223    
1224    /* motion estimation for B-frames */
1225    
1226  static __inline VECTOR  static __inline VECTOR
1227  ChoosePred(const MACROBLOCK * const pMB, const uint32_t mode)  ChoosePred(const MACROBLOCK * const pMB, const uint32_t mode)
1228  {  {
1229  /* the stupidiest function ever */  /* the stupidiest function ever */
1230          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];  
1231  }  }
1232    
1233  static void __inline  static void __inline
# Line 896  Line 1245 
1245          pmv[2] = ChoosePred(pMB, mode_curr);          pmv[2] = ChoosePred(pMB, mode_curr);
1246          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);
1247    
         pmv[3].x = pmv[3].y = 0;  
1248          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour
1249                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);
1250                  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);
1251            } else pmv[3].x = pmv[3].y = 0;
1252    
1253          if (y != 0) {          if (y != 0) {
1254                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);
# Line 911  Line 1260 
1260                  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);
1261          } else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
1262    
1263          if ((x != 0)&&(y != 0)) {          if (x != 0 && y != 0) {
1264                  pmv[6] = ChoosePred(pMB-1-iWcount, mode_curr);                  pmv[6] = ChoosePred(pMB-1-iWcount, mode_curr);
1265                  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);
1266          } else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
   
 // more?  
1267  }  }
1268    
1269    
1270  /* search backward or forward, for b-frames */  /* search backward or forward */
1271  static void  static void
1272  SearchBF(       const uint8_t * const pRef,  SearchBF(       const uint8_t * const pRef,
1273                          const uint8_t * const pRefH,                          const uint8_t * const pRefH,
# Line 929  Line 1276 
1276                          const IMAGE * const pCur,                          const IMAGE * const pCur,
1277                          const int x, const int y,                          const int x, const int y,
1278                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
1279                          const uint32_t iFcode,                          const uint32_t iFcode,
1280                          const MBParam * const pParam,                          const MBParam * const pParam,
1281                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
1282                          const VECTOR * const predMV,                          const VECTOR * const predMV,
1283                          int32_t * const best_sad,                          int32_t * const best_sad,
1284                          const int32_t mode_current)                          const int32_t mode_current,
1285                            SearchData * const Data)
1286  {  {
1287    
1288          const int32_t iEdgedWidth = pParam->edged_width;          int i, iDirection = 255, mask;
1289            VECTOR pmv[7];
         int i, iDirection, mask;  
         VECTOR currentMV, pmv[7];  
1290          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1291          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
1292          SearchData Data;          Data->iFcode = iFcode;
1293            Data->qpel_precision = 0;
1294    
1295          Data.iMinSAD = &iMinSAD;          Data->Ref = pRef + (x + y * Data->iEdgedWidth) * 16;
1296          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->RefH = pRefH + (x + y * Data->iEdgedWidth) * 16;
1297          Data.iEdgedWidth = iEdgedWidth;          Data->RefV = pRefV + (x + y * Data->iEdgedWidth) * 16;
1298          Data.currentMV = &currentMV;          Data->RefHV = pRefHV + (x + y * Data->iEdgedWidth) * 16;
1299          Data.iMinSAD = &iMinSAD;  
1300          Data.Ref = pRef + (x + y * iEdgedWidth) * 16;          Data->predMV = *predMV;
1301          Data.RefH = pRefH + (x + y * iEdgedWidth) * 16;  
1302          Data.RefV = pRefV + (x + y * iEdgedWidth) * 16;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1303          Data.RefHV = pRefHV + (x + y * iEdgedWidth) * 16;                                  pParam->width, pParam->height, iFcode - Data->qpel, 0, 0);
   
         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);  
1304    
1305          currentMV.x = currentMV.y = 0;          pmv[0] = Data->predMV;
1306            if (Data->qpel) { pmv[0].x /= 2; pmv[0].y /= 2; }
1307    
1308            PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
1309    
1310            Data->currentMV->x = Data->currentMV->y = 0;
1311          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1312    
1313  // main loop. checking all predictions  // main loop. checking all predictions
1314          for (i = 0; i < 8; i++) {          for (i = 0; i < 7; i++) {
1315                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1316                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1317          }          }
1318    
1319          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
1320                  MainSearchPtr = SquareSearch;          else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
         else if (MotionFlags & PMV_ADVANCEDDIAMOND16)  
                 MainSearchPtr = AdvDiamondSearch;  
1321                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1322    
1323          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1324    
1325          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          SubpelRefine(Data);
1326    
1327            if (Data->qpel && *Data->iMinSAD < *best_sad + 300) {
1328                    Data->currentQMV->x = 2*Data->currentMV->x;
1329                    Data->currentQMV->y = 2*Data->currentMV->y;
1330                    Data->qpel_precision = 1;
1331                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1332                                            pParam->width, pParam->height, iFcode, 1, 0);
1333                    SubpelRefine(Data);
1334            }
1335    
1336  // 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];  
1337    
1338            if (mode_current == MODE_FORWARD) *Data->iMinSAD += 4 * Data->lambda16;
1339            else *Data->iMinSAD += 3 * Data->lambda16;
1340    
1341          if (iMinSAD < *best_sad) {          if (*Data->iMinSAD < *best_sad) {
1342                  *best_sad = iMinSAD;                  *best_sad = *Data->iMinSAD;
1343                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1344                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  if (Data->qpel) {
1345                  pMB->pmvs[0].y = currentMV.y - predMV->y;                          pMB->pmvs[0].x = Data->currentQMV->x - predMV->x;
1346                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                          pMB->pmvs[0].y = Data->currentQMV->y - predMV->y;
1347                  else pMB->b_mvs[0] = currentMV;                          if (mode_current == MODE_FORWARD)
1348                                    pMB->qmvs[0] = *Data->currentQMV;
1349                            else
1350                                    pMB->b_qmvs[0] = *Data->currentQMV;
1351                    } else {
1352                            pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1353                            pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1354                    }
1355                    if (mode_current == MODE_FORWARD) pMB->mvs[0] = *Data->currentMV;
1356                    else pMB->b_mvs[0] = *Data->currentMV;
1357          }          }
1358    
1359            if (mode_current == MODE_FORWARD) *(Data->currentMV+2) = *Data->currentMV;
1360            else *(Data->currentMV+1) = *Data->currentMV; //we store currmv for interpolate search
1361  }  }
1362    
1363  static int32_t  static void
1364  SearchDirect(const uint8_t * const f_Ref,  SkipDecisionB(const IMAGE * const pCur,
1365                                    const IMAGE * const f_Ref,
1366                                    const IMAGE * const b_Ref,
1367                                    MACROBLOCK * const pMB,
1368                                    const uint32_t x, const uint32_t y,
1369                                    const SearchData * const Data)
1370    {
1371            int dx = 0, dy = 0, b_dx = 0, b_dy = 0;
1372            int32_t sum;
1373            const int div = 1 + Data->qpel;
1374            int k;
1375            const uint32_t stride = Data->iEdgedWidth/2;
1376    //this is not full chroma compensation, only it's fullpel approximation. should work though
1377    
1378            for (k = 0; k < 4; k++) {
1379                    dy += Data->directmvF[k].y / div;
1380                    dx += Data->directmvF[0].x / div;
1381                    b_dy += Data->directmvB[0].y / div;
1382                    b_dx += Data->directmvB[0].x / div;
1383            }
1384    
1385            dy = (dy >> 3) + roundtab_76[dy & 0xf];
1386            dx = (dx >> 3) + roundtab_76[dx & 0xf];
1387            b_dy = (b_dy >> 3) + roundtab_76[b_dy & 0xf];
1388            b_dx = (b_dx >> 3) + roundtab_76[b_dx & 0xf];
1389    
1390            sum = sad8bi(pCur->u + 8 * x + 8 * y * stride,
1391                                            f_Ref->u + (y*8 + dy/2) * stride + x*8 + dx/2,
1392                                            b_Ref->u + (y*8 + b_dy/2) * stride + x*8 + b_dx/2,
1393                                            stride);
1394    
1395            if (sum >= 2 * MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) return; //no skip
1396    
1397            sum += sad8bi(pCur->v + 8*x + 8 * y * stride,
1398                                            f_Ref->v + (y*8 + dy/2) * stride + x*8 + dx/2,
1399                                            b_Ref->v + (y*8 + b_dy/2) * stride + x*8 + b_dx/2,
1400                                            stride);
1401    
1402            if (sum < 2 * MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) pMB->mode = MODE_DIRECT_NONE_MV; //skipped
1403    }
1404    
1405    static __inline uint32_t
1406    SearchDirect(const IMAGE * const f_Ref,
1407                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1408                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
1409                                  const uint8_t * const f_RefHV,                                  const uint8_t * const f_RefHV,
1410                                  const uint8_t * const b_Ref,                                  const IMAGE * const b_Ref,
1411                                  const uint8_t * const b_RefH,                                  const uint8_t * const b_RefH,
1412                                  const uint8_t * const b_RefV,                                  const uint8_t * const b_RefV,
1413                                  const uint8_t * const b_RefHV,                                  const uint8_t * const b_RefHV,
1414                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1415                                  const int x, const int y,                                  const int x, const int y,
1416                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1417                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1418                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1419                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1420                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1421                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1422                                    SearchData * const Data)
1423    
1424  {  {
1425          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
1426          int32_t iMinSAD = 0, skip_sad;          int k = (x + Data->iEdgedWidth*y) * 16;
         int k;  
         VECTOR currentMV;  
1427          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
         SearchData Data;  
1428    
1429          Data.iMinSAD = &iMinSAD;          *Data->iMinSAD = 256*4096;
1430          Data.Cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;          Data->Ref = f_Ref->y + k;
1431          Data.iEdgedWidth = iEdgedWidth;          Data->RefH = f_RefH + k;
1432          Data.currentMV = &currentMV;          Data->RefV = f_RefV + k;
1433          Data.iQuant = iQuant;          Data->RefHV = f_RefHV + k;
1434          Data.referencemv = b_mb->mvs;          Data->bRef = b_Ref->y + k;
1435            Data->bRefH = b_RefH + k;
1436          Data.Ref= f_Ref + (x + iEdgedWidth*y) * 16;          Data->bRefV = b_RefV + k;
1437          Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;          Data->bRefHV = b_RefHV + k;
1438          Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;  
1439          Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;          k = Data->qpel ? 4 : 2;
1440          Data.bRef = b_Ref + (x + iEdgedWidth*y) * 16;          Data->max_dx = k * (pParam->width - x * 16);
1441          Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;          Data->max_dy = k * (pParam->height - y * 16);
1442          Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;          Data->min_dx = -k * (16 + x * 16);
1443          Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;          Data->min_dy = -k * (16 + y * 16);
1444  /*  
1445  //What we do here is a complicated version of CheckCandidateDirect(0,0);          Data->referencemv = Data->qpel ? b_mb->qmvs : b_mb->mvs;
1446  get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16, pParam->width, pParam->height, 19);          Data->qpel_precision = 0;
   
 */  
         Data.max_dx = 2 * pParam->width - 2 * (x) * 16;  
         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);  
1447    
1448          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1449                  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);
1450                  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;
1451                  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);
1452                  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;
1453    
1454          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)
1455                          || ( 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) ) {
1456                          || ( 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 )) {  
 /*  
                 fprintf(debug, "\nERROR - out of range : vector %d,%d and %d,%d\n", pMB->mvs[k].x, pMB->mvs[k].y,pMB->b_mvs[k].x,pMB->b_mvs[k].y );  
                 fprintf(debug, " range is x: %d..%d y: %d..%d \n", Data.min_dx,Data.max_dx,Data.min_dy,Data.max_dy);  
                 fprintf(debug,"macroblock %d, %d \n", x, y);  
                 fprintf(debug, "direct MV is %d,%d \n", directmv[k].x, directmv[k].y);  
 */  
1457                  *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
1458                  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"
1459                  pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;  /* because backwards and interpol might rely on this */                          pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;
1460                  return 0; }                          return 256*4096;
1461                    }
1462                    if (b_mb->mode != MODE_INTER4V) {
1463                            pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1464                            pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];
1465                            Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1466                            Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1467                            break;
1468                    }
1469            }
1470    
1471            CheckCandidate = b_mb->mode == MODE_INTER4V ? CheckCandidateDirect : CheckCandidateDirectno4v;
1472    
1473          if (b_mb->mode != MODE_INTER4V) {          (*CheckCandidate)(0, 0, 255, &k, Data);
1474                  iMinSAD = sad16bi(Data.Cur,  
1475                                                  get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,  // initial (fast) skip decision
1476                                                                  x, y, 16, &pMB->mvs[0], iEdgedWidth),          if (*Data->iMinSAD < pMB->quant * INITIAL_SKIP_THRESH * 2) {
1477                                                  get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,                  //possible skip - checking chroma
1478                                                                  x, y, 16, &pMB->b_mvs[0], iEdgedWidth), iEdgedWidth);                  SkipDecisionB(pCur, f_Ref, b_Ref, pMB, x, y, Data);
1479                    if (pMB->mode == MODE_DIRECT_NONE_MV) return *Data->iMinSAD; // skip.
1480                  Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];          }
1481                  Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];  
1482                  break;          skip_sad = *Data->iMinSAD;
         }  
         iMinSAD += sad8bi(Data.Cur + (k&1)*8 + (k>>1)* 8 * iEdgedWidth,  
                                                 get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,  
                                                                 (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->mvs[k], iEdgedWidth),  
                                                 get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,  
                                                                 (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->b_mvs[k], iEdgedWidth),  
                                                 iEdgedWidth);  
         }  
   
 // skip decision  
         if (iMinSAD < (int32_t)iQuant * SKIP_THRESH_B) {  
                 pMB->mode = MODE_DIRECT_NONE_MV;  
                 return iMinSAD; }  
   
         skip_sad = iMinSAD;  
         iMinSAD += 2 * lambda_vec16[iQuant]; // 2 bits needed to code vector 0,0  
         currentMV.x = currentMV.y = 0;  
         if (b_mb->mode == MODE_INTER4V)  
                 CheckCandidate = CheckCandidateDirect;  
         else CheckCandidate = CheckCandidateDirectno4v;  
1483    
1484  //  DIRECT MODE DELTA VECTOR SEARCH.  //  DIRECT MODE DELTA VECTOR SEARCH.
1485  //      This has to be made more effective, but at the moment I'm happy it's running at all  //      This has to be made more effective, but at the moment I'm happy it's running at all
# Line 1123  Line 1488 
1488                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1489                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1490    
1491          (*MainSearchPtr)(0, 0, &Data, 255);          (*MainSearchPtr)(0, 0, Data, 255);
1492    
1493          HalfpelRefine(&Data);          SubpelRefine(Data);
1494    
1495          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;  
1496    
1497          if (b_mb->mode == MODE_INTER4V)          if (Data->qpel || b_mb->mode == MODE_INTER4V) pMB->mode = MODE_DIRECT;
                 pMB->mode = MODE_DIRECT;  
1498          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1499    
1500          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1501    
1502          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1503                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1504                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = (     (Data->currentMV->x == 0)
1505                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1506                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          :pMB->mvs[k].x - Data->referencemv[k].x);
1507                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1508                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1509                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1510                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1511                    if (Data->qpel) {
1512                            pMB->qmvs[k].x = pMB->mvs[k].x; pMB->mvs[k].x /= 2;
1513                            pMB->b_qmvs[k].x = pMB->b_mvs[k].x; pMB->b_mvs[k].x /= 2;
1514                            pMB->qmvs[k].y = pMB->mvs[k].y; pMB->mvs[k].y /= 2;
1515                            pMB->b_qmvs[k].y = pMB->b_mvs[k].y; pMB->b_mvs[k].y /= 2;
1516                    }
1517    
1518                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1519                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1520                          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];
1521                            pMB->qmvs[3] = pMB->qmvs[2] = pMB->qmvs[1] = pMB->qmvs[0];
1522                            pMB->b_qmvs[3] = pMB->b_qmvs[2] = pMB->b_qmvs[1] = pMB->b_qmvs[0];
1523                          break;                          break;
1524                  }                  }
1525          }          }
1526          return 0;//skip_sad;          return skip_sad;
1527  }  }
1528    
1529  static __inline void  static void
1530  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const uint8_t * const f_Ref,
1531                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1532                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
# Line 1168  Line 1540 
1540                                  const uint32_t fcode,                                  const uint32_t fcode,
1541                                  const uint32_t bcode,                                  const uint32_t bcode,
1542                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1543                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1544                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1545                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1546                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1547                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1548                                    SearchData * const fData)
1549    
1550  {  {
 /* 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;  
1551    
1552          int iDirection, i, j;          int iDirection, i, j;
1553          int32_t iMinSAD = 256*4096;          SearchData bData;
         VECTOR currentMV[3];  
         SearchData fData, bData;  
   
   
         fData.iMinSAD = bData.iMinSAD = &iMinSAD;  
1554    
1555          fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          fData->qpel_precision = 0;
1556          fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;          memcpy(&bData, fData, sizeof(SearchData)); //quick copy of common data
1557          fData.currentMV = currentMV; bData.currentMV = currentMV + 1;          *fData->iMinSAD = 4096*256;
1558          fData.iQuant = bData.iQuant = iQuant;          bData.currentMV++; bData.currentQMV++;
1559          fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;          fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1560    
1561            i = (x + y * fData->iEdgedWidth) * 16;
1562            bData.bRef = fData->Ref = f_Ref + i;
1563            bData.bRefH = fData->RefH = f_RefH + i;
1564            bData.bRefV = fData->RefV = f_RefV + i;
1565            bData.bRefHV = fData->RefHV = f_RefHV + i;
1566            bData.Ref = fData->bRef = b_Ref + i;
1567            bData.RefH = fData->bRefH = b_RefH + i;
1568            bData.RefV = fData->bRefV = b_RefV + i;
1569            bData.RefHV = fData->bRefHV = b_RefHV + i;
1570    
1571            bData.bpredMV = fData->predMV = *f_predMV;
1572            fData->bpredMV = bData.predMV = *b_predMV;
1573            fData->currentMV[0] = fData->currentMV[2];
1574    
1575            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);
1576            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);
1577    
1578            if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1579            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dx;
1580            if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dy;
1581            if (fData->currentMV[0].y < fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1582    
1583            if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1584            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dx;
1585            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dy;
1586            if (fData->currentMV[1].y < bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1587    
1588            CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
1589    
1590          bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  //diamond
         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);  
   
         CheckCandidateInt(currentMV[0].x, currentMV[0].y, 255, &iDirection, &fData);  
   
 //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  
   
1591          do {          do {
1592                  iDirection = 255;                  iDirection = 255;
1593                  // forward MV moves                  // forward MV moves
1594                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
1595    
1596                  CheckCandidateInt(i + 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1597                  CheckCandidateInt(i, j + 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1598                  CheckCandidateInt(i - 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1599                  CheckCandidateInt(i, j - 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
1600    
1601                  // backward MV moves                  // backward MV moves
1602                  i = currentMV[1].x; j = currentMV[1].y;                  i = fData->currentMV[1].x; j = fData->currentMV[1].y;
1603                  currentMV[2] = currentMV[0];                  fData->currentMV[2] = fData->currentMV[0];
1604                    CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1605                  CheckCandidateInt(i + 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1606                  CheckCandidateInt(i, j + 2, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
1607                  CheckCandidateInt(i - 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, &bData);
                 CheckCandidateInt(i, j - 2, 0, &iDirection, &bData);  
1608    
1609          } while (!(iDirection));          } while (!(iDirection));
1610    
1611  /* halfpel refinement. luckly we can use normal halfpel function for it */  //qpel refinement
1612            if (fData->qpel) {
1613          if (MotionFlags & PMV_HALFPELREFINE16) {                  if (*fData->iMinSAD > *best_sad + 500) return;
1614                  CheckCandidate = CheckCandidateInt;                  CheckCandidate = CheckCandidateInt;
1615                  HalfpelRefine(&fData);                  fData->qpel_precision = bData.qpel_precision = 1;
1616                  currentMV[2] = currentMV[0];                  get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, 1, 0);
1617                  HalfpelRefine(&bData);                  get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, 1, 0);
1618          }                  fData->currentQMV[2].x = fData->currentQMV[0].x = 2 * fData->currentMV[0].x;
1619                    fData->currentQMV[2].y = fData->currentQMV[0].y = 2 * fData->currentMV[0].y;
1620  // two bits are needed to code interpolate mode. we treat the bits just like they were vector's                  fData->currentQMV[1].x = 2 * fData->currentMV[1].x;
1621          iMinSAD +=  2 * lambda_vec16[iQuant];                  fData->currentQMV[1].y = 2 * fData->currentMV[1].y;
1622          if (iMinSAD < *best_sad) {                  SubpelRefine(fData);
1623                  *best_sad = iMinSAD;                  if (*fData->iMinSAD > *best_sad + 300) return;
1624                  pMB->mvs[0] = currentMV[0];                  fData->currentQMV[2] = fData->currentQMV[0];
1625                  pMB->b_mvs[0] = currentMV[1];                  SubpelRefine(&bData);
1626            }
1627    
1628            *fData->iMinSAD += (2+3) * fData->lambda16; // two bits are needed to code interpolate mode.
1629    
1630            if (*fData->iMinSAD < *best_sad) {
1631                    *best_sad = *fData->iMinSAD;
1632                    pMB->mvs[0] = fData->currentMV[0];
1633                    pMB->b_mvs[0] = fData->currentMV[1];
1634                  pMB->mode = MODE_INTERPOLATE;                  pMB->mode = MODE_INTERPOLATE;
1635                    if (fData->qpel) {
1636                            pMB->qmvs[0] = fData->currentQMV[0];
1637                            pMB->b_qmvs[0] = fData->currentQMV[1];
1638                            pMB->pmvs[1].x = pMB->qmvs[0].x - f_predMV->x;
1639                            pMB->pmvs[1].y = pMB->qmvs[0].y - f_predMV->y;
1640                            pMB->pmvs[0].x = pMB->b_qmvs[0].x - b_predMV->x;
1641                            pMB->pmvs[0].y = pMB->b_qmvs[0].y - b_predMV->y;
1642                    } else {
1643                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;
1644                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;
1645                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;
1646                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;
1647          }          }
1648  }  }
1649    }
1650    
1651  void  void
1652  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
# Line 1277  Line 1660 
1660                                           const IMAGE * const f_refV,                                           const IMAGE * const f_refV,
1661                                           const IMAGE * const f_refHV,                                           const IMAGE * const f_refHV,
1662                                           // backward (future) reference                                           // backward (future) reference
1663                                           const MACROBLOCK * const b_mbs,                                           const FRAMEINFO * const b_reference,
1664                                           const IMAGE * const b_ref,                                           const IMAGE * const b_ref,
1665                                           const IMAGE * const b_refH,                                           const IMAGE * const b_refH,
1666                                           const IMAGE * const b_refV,                                           const IMAGE * const b_refV,
1667                                           const IMAGE * const b_refHV)                                           const IMAGE * const b_refHV)
1668  {  {
1669          uint32_t i, j;          uint32_t i, j;
1670          int32_t best_sad, skip_sad;          int32_t best_sad;
1671            uint32_t skip_sad;
1672          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;
1673          static const VECTOR zeroMV={0,0};          const MACROBLOCK * const b_mbs = b_reference->mbs;
1674    
1675          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
1676    
1677          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1678          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
1679    
1680          // note: i==horizontal, j==vertical  // some pre-inintialized data for the rest of the search
1681    
1682            SearchData Data;
1683            int32_t iMinSAD;
1684            VECTOR currentMV[3];
1685            VECTOR currentQMV[3];
1686            memset(&Data, 0, sizeof(SearchData));
1687            Data.iEdgedWidth = pParam->edged_width;
1688            Data.currentMV = currentMV; Data.currentQMV = currentQMV;
1689            Data.iMinSAD = &iMinSAD;
1690            Data.lambda16 = lambda_vec16[frame->quant];
1691            Data.chroma = frame->quant;
1692            Data.qpel = pParam->m_quarterpel;
1693            Data.rounding = 0;
1694    
1695            Data.RefQ = f_refV->u; // a good place, also used in MC (for similar purpose)
1696            // note: i==horizontal, j==vertical
1697          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
1698    
1699                  f_predMV = b_predMV = zeroMV;   /* prediction is reset at left boundary */                  f_predMV = b_predMV = zeroMV;   /* prediction is reset at left boundary */
# Line 1303  Line 1702 
1702                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;
1703                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;
1704    
1705  /* 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 */
1706                            if (b_reference->coding_type != S_VOP)
1707                          if (b_mb->mode == MODE_NOT_CODED) {                          if (b_mb->mode == MODE_NOT_CODED) {
1708                                  pMB->mode = MODE_NOT_CODED;                                  pMB->mode = MODE_NOT_CODED;
1709                                  continue;                                  continue;
1710                          }                          }
1711    
1712                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
1713                            pMB->quant = frame->quant;
1714    
1715  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
1716          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
1717                            skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
1718                          skip_sad = SearchDirect(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,  
1719                                                                          &frame->image,                                                                          &frame->image,
1720                                                                          i, j,                                                                          i, j,
1721                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
1722                                                                          TRB, TRD,                                                                          TRB, TRD,
1723                                                                          pParam,                                                                          pParam,
1724                                                                          pMB, b_mb,                                                                          pMB, b_mb,
1725                                                                          &best_sad);                                                                          &best_sad,
1726                                                                            &Data);
1727    
                         if (!(frame->global_flags & XVID_HALFPEL)) best_sad = skip_sad = 256*4096;  
                         else  
1728                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1729    
 //                      best_sad = 256*4096; //uncomment to disable Directsearch.  
 //      To disable any other mode, just comment the function call  
   
1730                          // forward search                          // forward search
1731                          SearchBF(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                          SearchBF(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
1732                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1733                                                  frame->motion_flags,                                                  frame->motion_flags,
1734                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
1735                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
1736                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
1737    
1738                          // backward search                          // backward search
1739                          SearchBF(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                          SearchBF(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
1740                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1741                                                  frame->motion_flags,                                                  frame->motion_flags,
1742                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
1743                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
1744                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
1745    
1746                          // 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
   
1747                          SearchInterpolate(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                          SearchInterpolate(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
1748                                                  b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                                                  b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
1749                                                  &frame->image,                                                  &frame->image,
1750                                                  i, j,                                                  i, j,
1751                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
1752                                                  frame->motion_flags,                                                  frame->motion_flags,
1753                                                  frame->quant, pParam,                                                  pParam,
1754                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
1755                                                  pMB, &best_sad);                                                  pMB, &best_sad,
1756                                                    &Data);
1757    
1758    // final skip decision
1759                            if ( (skip_sad < frame->quant * MAX_SAD00_FOR_SKIP*2)
1760                                            && ((100*best_sad)/(skip_sad+1) > FINAL_SKIP_THRESH) )
1761                                    SkipDecisionB(&frame->image, f_ref, b_ref, pMB, i, j, &Data);
1762    
1763                          switch (pMB->mode) {                          switch (pMB->mode) {
1764                                  case MODE_FORWARD:                                  case MODE_FORWARD:
1765                                          f_count++;                                          f_count++;
1766                                          f_predMV = pMB->mvs[0];                                          f_predMV = Data.qpel ? pMB->qmvs[0] : pMB->mvs[0];
1767                                          break;                                          break;
1768                                  case MODE_BACKWARD:                                  case MODE_BACKWARD:
1769                                          b_count++;                                          b_count++;
1770                                          b_predMV = pMB->b_mvs[0];                                          b_predMV = Data.qpel ? pMB->b_qmvs[0] : pMB->b_mvs[0];
1771                                          break;                                          break;
1772                                  case MODE_INTERPOLATE:                                  case MODE_INTERPOLATE:
1773                                          i_count++;                                          i_count++;
1774                                          f_predMV = pMB->mvs[0];                                          f_predMV = Data.qpel ? pMB->qmvs[0] : pMB->mvs[0];
1775                                          b_predMV = pMB->b_mvs[0];                                          b_predMV = Data.qpel ? pMB->b_qmvs[0] : pMB->b_mvs[0];
1776                                          break;                                          break;
1777                                  case MODE_DIRECT:                                  case MODE_DIRECT:
1778                                  case MODE_DIRECT_NO4V:                                  case MODE_DIRECT_NO4V:
1779                                          d_count++;                                          d_count++;
                                         break;  
1780                                  default:                                  default:
1781                                          break;                                          break;
1782                          }                          }
1783                  }                  }
1784          }          }
   
 //      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);  
   
1785  }  }
1786    
 /* Hinted ME starts here */  
   
1787  static __inline void  static __inline void
1788  Search8hinted(  const SearchData * const OldData,  MEanalyzeMB (   const uint8_t * const pRef,
1789                                  const int x, const int y,                                  const uint8_t * const pCur,
1790                                  const uint32_t MotionFlags,                                  const int x,
1791                                    const int y,
1792                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1793                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMBs,
1794                                  const MACROBLOCK * const pMBs,                                  SearchData * const Data)
                                 const int block)  
1795  {  {
         SearchData Data;  
         MainSearchFunc *MainSearchPtr;  
1796    
1797          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          int i, mask;
1798          Data.iMinSAD = OldData->iMinSAD + 1 + block;          VECTOR pmv[3];
1799          Data.currentMV = OldData->currentMV+1+block;          MACROBLOCK * pMB = &pMBs[x + y * pParam->mb_width];
         Data.iFcode = OldData->iFcode;  
         Data.iQuant = OldData->iQuant;  
   
         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));  
         Data.iEdgedWidth = pParam->edged_width;  
         Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));  
1800    
1801          CheckCandidate = CheckCandidate8;          for (i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
1802    
1803          if (block != 0)          //median is only used as prediction. it doesn't have to be real
1804                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *          if (x == 1 && y == 1) Data->predMV.x = Data->predMV.y = 0;
1805                                                                  d_mv_bits(      Data.currentMV->x - Data.predMV.x,          else
1806                                                                                          Data.currentMV->y - Data.predMV.y,                  if (x == 1) //left macroblock does not have any vector now
1807                                                                                          Data.iFcode);                          Data->predMV = (pMB - pParam->mb_width)->mvs[0]; // top instead of median
1808                    else if (y == 1) // top macroblock doesn't have it's vector
1809                            Data->predMV = (pMB - 1)->mvs[0]; // left instead of median
1810                            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); //else median
1811    
1812            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1813                                    pParam->width, pParam->height, Data->iFcode - pParam->m_quarterpel, 0, Data->rrv);
1814    
1815          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,          Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
1816                                  pParam->width, pParam->height, OldData->iFcode);          Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
1817    
1818          if (pMB->mode == MODE_INTER4V) {          pmv[1].x = EVEN(pMB->mvs[0].x);
1819                  int dummy;          pmv[1].y = EVEN(pMB->mvs[0].y);
1820                  CheckCandidate8(pMB->mvs[block].x, pMB->mvs[block].y, 0, &dummy, &Data); }          pmv[2].x = EVEN(Data->predMV.x);
1821            pmv[2].y = EVEN(Data->predMV.y);
1822            pmv[0].x = pmv[0].y = 0;
1823    
1824          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;          CheckCandidate32I(0, 0, 255, &i, Data);
1825                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;  
1826                          else MainSearchPtr = DiamondSearch;          if (*Data->iMinSAD > 4 * MAX_SAD00_FOR_SKIP * 4) {
1827    
1828          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);                  if (!(mask = make_mask(pmv, 1)))
1829                            CheckCandidate32I(pmv[1].x, pmv[1].y, mask, &i, Data);
1830                    if (!(mask = make_mask(pmv, 2)))
1831                            CheckCandidate32I(pmv[2].x, pmv[2].y, mask, &i, Data);
1832    
1833          if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                  if (*Data->iMinSAD > 4 * MAX_SAD00_FOR_SKIP * 4) // diamond only if needed
1834                            DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
1835    
1836          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;                  for (i = 0; i < 4; i++) {
1837          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;                          MACROBLOCK * MB = &pMBs[x + (i&1) + (y+(i>>1)) * pParam->mb_width];
1838          pMB->mvs[block] = *(Data.currentMV);                          MB->mvs[0] = MB->mvs[1] = MB->mvs[2] = MB->mvs[3] = Data->currentMV[i];
1839          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                          MB->mode = MODE_INTER;
1840                            MB->sad16 = Data->iMinSAD[i+1];
1841                    }
1842            }
1843  }  }
1844    
1845    #define INTRA_BIAS              2500
1846    #define INTRA_THRESH    1500
1847    #define INTER_THRESH    1400
1848    
1849  static void  int
1850  SearchPhinted ( const uint8_t * const pRef,  MEanalysis(     const IMAGE * const pRef,
1851                                  const uint8_t * const pRefH,                          FRAMEINFO * const Current,
1852                                  const uint8_t * const pRefV,                          MBParam * const pParam,
1853                                  const uint8_t * const pRefHV,                          int maxIntra, //maximum number if non-I frames
1854                                  const IMAGE * const pCur,                          int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame
1855                                  const int x,                          int bCount) // number of B frames in a row
                                 const int y,  
                                 const uint32_t MotionFlags,  
                                 const uint32_t iQuant,  
                                 const uint32_t iFcode,  
                                 const MBParam * const pParam,  
                                 const MACROBLOCK * const pMBs,  
                                 int inter4v,  
                                 MACROBLOCK * const pMB)  
1856  {  {
1857            uint32_t x, y, intra = 0;
1858            int sSAD = 0;
1859            MACROBLOCK * const pMBs = Current->mbs;
1860            const IMAGE * const pCurrent = &Current->image;
1861            int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH;
1862    
1863          const int32_t iEdgedWidth = pParam->edged_width;          int32_t iMinSAD[5], temp[5];
   
         int i;  
1864          VECTOR currentMV[5];          VECTOR currentMV[5];
         int32_t iMinSAD[5];  
         int32_t temp[5];  
         MainSearchFunc * MainSearchPtr;  
1865          SearchData Data;          SearchData Data;
1866            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;  
1867          Data.currentMV = currentMV;          Data.currentMV = currentMV;
1868          Data.iMinSAD = iMinSAD;          Data.iMinSAD = iMinSAD;
1869          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data.iFcode = Current->fcode;
1870          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data.rrv = Current->global_flags & XVID_REDUCED;
         Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;  
         Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;  
1871          Data.temp = temp;          Data.temp = temp;
1872          Data.iQuant = iQuant;          CheckCandidate = CheckCandidate32I;
         Data.iFcode = 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);  
         }  
   
         for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;  
   
         if (pMB->dquant != NO_CHANGE) inter4v = 0;  
   
         if (inter4v)  
                 CheckCandidate = CheckCandidate16;  
         else CheckCandidate = CheckCandidate16no4v;  
   
1873    
1874          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);          if (intraCount != 0 && intraCount < 10) // we're right after an I frame
1875          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);                  IntraThresh += 4 * (intraCount - 10) * (intraCount - 10);
1876          if (pMB->mvs[0].x > Data.max_dx) pMB->mvs[0].x = Data.max_dx; // this is in case iFcode changed          else
1877          if (pMB->mvs[0].x < Data.min_dx) pMB->mvs[0].x = Data.min_dx;                  if ( 5*(maxIntra - intraCount) < maxIntra) // we're close to maximum. 2 sec when max is 10 sec
1878          if (pMB->mvs[0].y > Data.max_dy) pMB->mvs[0].y = Data.max_dy;                          IntraThresh -= (IntraThresh * (maxIntra - 5*(maxIntra - intraCount)))/maxIntra;
         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;  
1879    
1880          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          InterThresh += 400 * (1 - bCount);
1881            if (InterThresh < 300) InterThresh = 300;
1882    
1883          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (sadInit) (*sadInit) ();
1884    
1885          if (inter4v)          for (y = 1; y < pParam->mb_height-1; y += 2) {
1886                  for(i = 0; i < 4; i++)                  for (x = 1; x < pParam->mb_width-1; x += 2) {
1887                          Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                          int i;
1888    
1889          if (!(inter4v) ||                          if (bCount == 0) pMBs[x + y * pParam->mb_width].mvs[0] = zeroMV;
                 (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {  
 // INTER MODE  
1890    
1891                  pMB->mode = MODE_INTER;                          MEanalyzeMB(pRef->y, pCurrent->y, x, y, pParam, pMBs, &Data);
                 pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]  
                         = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];  
1892    
1893                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                          for (i = 0; i < 4; i++) {
1894                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                                  int dev;
1895                                    MACROBLOCK *pMB = &pMBs[x+(i&1) + (y+(i>>1)) * pParam->mb_width];
1896                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                                  if (pMB->sad16 > IntraThresh) {
1897                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                                          dev = dev16(pCurrent->y + (x + (i&1) + (y + (i>>1)) * pParam->edged_width) * 16,
1898          } else {                                                                          pParam->edged_width);
1899  // INTER4V MODE; all other things are already set in Search8hinted                                          if (dev + IntraThresh < pMB->sad16) {
1900                  pMB->mode = MODE_INTER4V;                                                  pMB->mode = MODE_INTRA;
1901                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                                                  if (++intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return I_VOP;
1902                                            }
1903          }          }
1904                                    sSAD += pMB->sad16;
1905                            }
1906                    }
1907            }
1908            sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
1909            if (sSAD > IntraThresh + INTRA_BIAS) return I_VOP;
1910            if (sSAD > InterThresh ) return P_VOP;
1911            emms();
1912            return B_VOP;
1913    
1914  }  }
1915    
1916  void  static void
1917  MotionEstimationHinted( MBParam * const pParam,  CheckGMC(int x, int y, const int dir, int * iDirection,
1918                                                  FRAMEINFO * const current,                  const MACROBLOCK * const pMBs, uint32_t * bestcount, VECTOR * GMC,
1919                                                  FRAMEINFO * const reference,                  const MBParam * const pParam)
                                                 const IMAGE * const pRefH,  
                                                 const IMAGE * const pRefV,  
                                                 const IMAGE * const pRefHV)  
1920  {  {
1921          MACROBLOCK *const pMBs = current->mbs;          uint32_t mx, my, a, count = 0;
         const IMAGE *const pCurrent = &current->image;  
         const IMAGE *const pRef = &reference->image;  
   
         uint32_t x, y;  
1922    
1923          if (sadInit) (*sadInit) ();          for (my = 1; my < pParam->mb_height-1; my++)
1924                    for (mx = 1; mx < pParam->mb_width-1; mx++) {
1925                            VECTOR mv;
1926                            const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
1927                            if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED) continue;
1928                            mv = pMB->mvs[0];
1929                            a = ABS(mv.x - x) + ABS(mv.y - y);
1930                            if (a < 6) count += 6 - a;
1931                    }
1932    
1933          for (y = 0; y < pParam->mb_height; y++) {          if (count > *bestcount) {
1934                  for (x = 0; x < pParam->mb_width; x++)  {                  *bestcount = count;
1935                          int32_t sad00;                  *iDirection = dir;
1936                    GMC->x = x; GMC->y = y;
1937            }
1938    }
1939    
                         MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];  
1940    
1941  //intra mode is copied from the first pass. At least for the time being  static VECTOR
1942                          if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;  GlobalMotionEst(const MACROBLOCK * const pMBs, const MBParam * const pParam, const uint32_t iFcode)
1943    {
1944    
1945                          if (!(current->global_flags & XVID_LUMIMASKING)) {          uint32_t count, bestcount = 0;
1946                                  pMB->dquant = NO_CHANGE;          int x, y;
1947                                  pMB->quant = current->quant; }          VECTOR gmc = {0,0};
1948            int step, min_x, max_x, min_y, max_y;
1949            uint32_t mx, my;
1950            int iDirection, bDirection;
1951    
1952                          if (pMB->dquant == NO_CHANGE) //no skip otherwise, anyway          min_x = min_y = -32<<iFcode;
1953                                  sad00 = pMB->sad16          max_x = max_y = 32<<iFcode;
                                         = sad16(pCurrent->y + (x + y * pParam->edged_width) * 16,  
                                                                 pRef->y + (x + y * pParam->edged_width) * 16,  
                                                                 pParam->edged_width, 256*4096 );  
                         else sad00 = 256*4096;  
1954    
1955    //step1: let's find a rough camera panning
1956            for (step = 32; step >= 2; step /= 2) {
1957                    bestcount = 0;
1958                    for (y = min_y; y <= max_y; y += step)
1959                            for (x = min_x ; x <= max_x; x += step) {
1960                                    count = 0;
1961                                    //for all macroblocks
1962                                    for (my = 1; my < pParam->mb_height-1; my++)
1963                                            for (mx = 1; mx < pParam->mb_width-1; mx++) {
1964                                                    const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
1965                                                    VECTOR mv;
1966    
1967  //initial skip decision                                                  if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
1968                                                            continue;
1969    
1970                          if ( (pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)                                                  mv = pMB->mvs[0];
1971                                  && ( //(pMB->mode == MODE_NOT_CODED) ||                                                  if ( ABS(mv.x - x) <= step && ABS(mv.y - y) <= step )   /* GMC translation is always halfpel-res */
1972                                          (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant) )) ) {                                                          count++;
1973                                  if (sad00 < pMB->quant * INITIAL_SKIP_THRESH) {                                          }
1974                                          SkipMacroblockP(pMB, sad00);                                  if (count >= bestcount) { bestcount = count; gmc.x = x; gmc.y = y; }
1975                                          continue; } //skipped                          }
1976                    min_x = gmc.x - step;
1977                    max_x = gmc.x + step;
1978                    min_y = gmc.y - step;
1979                    max_y = gmc.y + step;
1980                          }                          }
                         else sad00 = 256*4096;  
1981    
1982                          if (pMB->mode == MODE_NOT_CODED)          if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10)
1983                                  SearchP(        pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                  gmc.x = gmc.y = 0; //no camara pan, no GMC
                                                         y, current->motion_flags, pMB->quant,  
                                                         current->fcode, pParam, pMBs, reference->mbs,  
                                                         current->global_flags & XVID_INTER4V, pMB);  
1984    
1985                          else  // step2: let's refine camera panning using gradiend-descent approach
1986                                  SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,  // TODO: more warping points may be evaluated here (like in interpolate mode search - two vectors in one diamond)
1987                                                          y, current->motion_flags, pMB->quant,          bestcount = 0;
1988                                                          current->fcode, pParam, pMBs,          CheckGMC(gmc.x, gmc.y, 255, &iDirection, pMBs, &bestcount, &gmc, pParam);
1989                                                          current->global_flags & XVID_INTER4V, pMB);          do {
1990                    x = gmc.x; y = gmc.y;
1991                    bDirection = iDirection; iDirection = 0;
1992                    if (bDirection & 1) CheckGMC(x - 1, y, 1+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
1993                    if (bDirection & 2) CheckGMC(x + 1, y, 2+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
1994                    if (bDirection & 4) CheckGMC(x, y - 1, 1+2+4, &iDirection, pMBs, &bestcount, &gmc, pParam);
1995                    if (bDirection & 8) CheckGMC(x, y + 1, 1+2+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
1996    
1997  /* final skip decision, a.k.a. "the vector you found, really that good?" */          } while (iDirection);
                         if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)  
                                 if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)  
                                 SkipMacroblockP(pMB, sad00);  
1998    
1999                  }          if (pParam->m_quarterpel) {
2000          }                  gmc.x *= 2;
2001                    gmc.y *= 2;     /* we store the halfpel value as pseudo-qpel to make comparison easier */
2002  }  }
2003    
2004            return gmc;
2005    }

Legend:
Removed from v.530  
changed lines
  Added in v.768

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