[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 539, Wed Sep 25 21:28:48 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"
# Line 46  Line 48 
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 (22)  #define MAX_CHROMA_SAD_FOR_SKIP (22)
 #define SKIP_THRESH_B (25)  
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)
 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    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 */  /* 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;
         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 117  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 125  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                  data->currentMV[0].x = x; data->currentMV[0].y = y;                  current->x = x; current->y = y;
346                  *dir = Direction; }                  *dir = Direction; }
347  }  }
348    
349  static void  static void
350  CheckCandidate16no4vI(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidate32I(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
351  {  {
352          int32_t sad;  // maximum speed - for P/B/I decision
   
         if (( x > data->max_dx) || ( x < data->min_dx)  
                 || ( y > data->max_dy) || (y < data->min_dy)) return;  
353    
354          sad = lambda_vec16[data->iQuant] *          if ( (x > data->max_dx) | (x < data->min_dx)
355                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);                  | (y > data->max_dy) | (y < data->min_dy) ) return;
356    
357          sad += sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),          data->temp[0] = sad32v_c(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),
358                                          data->iEdgedWidth, 256*4096);                                                          data->iEdgedWidth, data->temp+1);
359    
360          if (sad < *(data->iMinSAD)) {          if (data->temp[0] < *(data->iMinSAD)) {
361                  *(data->iMinSAD) = sad;                  *(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;
385    
386          switch ( ((xf&1)<<1) + (yf&1) ) {          if (!data->qpel_precision) {
387                  case 0 : ReferenceF = data->Ref + xf/2 + (yf/2)*(data->iEdgedWidth); break;                  ReferenceF = GetReference(xf, yf, data);
388                  case 1 : ReferenceF = data->RefV + xf/2 + ((yf-1)/2)*(data->iEdgedWidth); break;                  xb = data->currentMV[1].x; yb = data->currentMV[1].y;
389                  case 2 : ReferenceF = data->RefH + (xf-1)/2 + (yf/2)*(data->iEdgedWidth); break;                  ReferenceB = GetReferenceB(xb, yb, 1, data);
390                  default : ReferenceF = data->RefHV + (xf-1)/2 + ((yf-1)/2)*(data->iEdgedWidth); break;                  current = data->currentMV;
391          }          } else {
392                    ReferenceF = Interpolate16x16qpel(xf, yf, 0, data);
393          switch ( ((xb&1)<<1) + (yb&1) ) {                  xb = data->currentQMV[1].x; yb = data->currentQMV[1].y;
394                  case 0 : ReferenceB = data->bRef + xb/2 + (yb/2)*(data->iEdgedWidth); break;                  current = data->currentQMV;
395                  case 1 : ReferenceB = data->bRefV + xb/2 + ((yb-1)/2)*(data->iEdgedWidth); break;                  ReferenceB = Interpolate16x16qpel(xb, yb, 1, data);
                 case 2 : ReferenceB = data->bRefH + (xb-1)/2 + (yb/2)*(data->iEdgedWidth); break;  
                 default : ReferenceB = data->bRefHV + (xb-1)/2 + ((yb-1)/2)*(data->iEdgedWidth); break;  
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 234  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 269  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 288  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 313  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 348  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 357  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 366  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 421  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 471  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 482  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 = 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 = 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 546  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          // some pre-initialized thingies for SearchP          // some pre-initialized thingies for SearchP
741          int32_t temp[5];          int32_t temp[8];
742          VECTOR currentMV[5];          VECTOR currentMV[5];
743            VECTOR currentQMV[5];
744          int32_t iMinSAD[5];          int32_t iMinSAD[5];
745          SearchData Data;          SearchData Data;
746          Data.iEdgedWidth = pParam->edged_width;          memset(&Data, 0, sizeof(SearchData));
747            Data.iEdgedWidth = iEdgedWidth;
748          Data.currentMV = currentMV;          Data.currentMV = currentMV;
749            Data.currentQMV = currentQMV;
750          Data.iMinSAD = iMinSAD;          Data.iMinSAD = iMinSAD;
751          Data.temp = temp;          Data.temp = temp;
752          Data.iFcode = current->fcode;          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            Data.RefQ = pRefV->u; // a good place, also used in MC (for similar purpose)
765          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
766    
767          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < mb_height; y++) {
768                  for (x = 0; x < pParam->mb_width; x++)  {                  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 );
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 );                                                          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                                                  &Data, 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->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  {  {
# Line 636  Line 871 
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;
# Line 673  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 700  Line 944 
944          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
945          VECTOR pmv[7];          VECTOR pmv[7];
946    
         get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()  
947          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
948                                  pParam->width, pParam->height, Data->iFcode);                                                  pParam->width, pParam->height, Data->iFcode - Data->qpel, 0, Data->rrv);
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 * Data->iEdgedWidth) * 16;  
         Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;  
         Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;  
         Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;  
         Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;  
   
         Data->iQuant = iQuant;  
   
         if (!(MotionFlags & PMV_HALFPEL16)) {  
                 Data->min_dx = EVEN(Data->min_dx);  
                 Data->max_dx = EVEN(Data->max_dx);  
                 Data->min_dy = EVEN(Data->min_dy);  
                 Data->max_dy = EVEN(Data->max_dy); }  
951    
952          for(i = 0;  i < 5; i++) Data->iMinSAD[i] = 256*4096;          Data->temp[5] = Data->temp[6] = 0; // chroma-sad cache
953            i = Data->rrv ? 2 : 1;
954            Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16*i;
955            Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
956            Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
957    
958            Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16*i;
959            Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16*i;
960            Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16*i;
961            Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16*i;
962            Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
963            Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
964    
965            Data->lambda16 = lambda_vec16[iQuant];
966            Data->lambda8 = lambda_vec8[iQuant];
967            Data->qpel_precision = 0;
968    
969          if (inter4v) CheckCandidate = CheckCandidate16;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
         else CheckCandidate = CheckCandidate16no4v;  
970    
971          (*CheckCandidate)(Data->predMV.x, Data->predMV.y, 0, &iDirection, Data);          for(i = 0; i < 5; i++)
972                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
973    
974          for(i = 0;  i < 5; i++) Data->currentMV[i].x = Data->currentMV[i].y = 0;          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(Data->predMV.x, Data->predMV.y, Data->iFcode);          i = d_mv_bits(0, 0, Data->predMV, Data->iFcode, 0, 0);
978          Data->iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;          Data->iMinSAD[0] = pMB->sad16 + ((Data->lambda16 * i * pMB->sad16)>>10);
979          Data->iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;          Data->iMinSAD[1] = pMB->sad8[0] + ((Data->lambda8 * i * (pMB->sad8[0]+NEIGH_8X8_BIAS)) >> 10);
980          Data->iMinSAD[2] = pMB->sad8[1];          Data->iMinSAD[2] = pMB->sad8[1];
981          Data->iMinSAD[3] = pMB->sad8[2];          Data->iMinSAD[3] = pMB->sad8[2];
982          Data->iMinSAD[4] = pMB->sad8[3];          Data->iMinSAD[4] = pMB->sad8[3];
983    
984          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (x | y) {
985                    threshA = Data->temp[0]; // that's when we keep this SAD atm
         if ((x == 0) && (y == 0)) threshA = 512;  
         else {  
                 threshA = Data->temp[0] + 20;  
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  /* main loop. checking all predictions */          if (!Data->rrv) {
994                    if (inter4v | Data->chroma) CheckCandidate = CheckCandidate16;
995                            else CheckCandidate = CheckCandidate16no4v; //for extra speed
996            } else CheckCandidate = CheckCandidate32;
997    
998    /* 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 (Data->iMinSAD[0] <= threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1004          }          }
1005    
1006          if ((Data->iMinSAD[0] <= threshA) ||          if ((Data->iMinSAD[0] <= threshA) ||
1007                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
1008                          (Data->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          } else {          else {
1011    
1012                  MainSearchFunc * MainSearchPtr;                  MainSearchFunc * MainSearchPtr;
1013                  if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;                  if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
# Line 774  Line 1023 
1023                  if (MotionFlags & PMV_EXTSEARCH16) {                  if (MotionFlags & PMV_EXTSEARCH16) {
1024                          int32_t bSAD;                          int32_t bSAD;
1025                          VECTOR startMV = Data->predMV, backupMV = Data->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 = Data->iMinSAD[0]; Data->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 < Data->iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1038                                          Data->currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
# Line 787  Line 1040 
1040                          }                          }
1041    
1042                          backupMV = Data->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 = Data->iMinSAD[0]; Data->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 < Data->iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1051                                          Data->currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
# Line 801  Line 1054 
1054                  }                  }
1055          }          }
1056    
1057          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);          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) {          if (inter4v) {
1074                  SearchData Data8;                  SearchData Data8;
1075                  Data8.iFcode = Data->iFcode;                  memcpy(&Data8, Data, sizeof(SearchData)); //quick copy of common data
1076                  Data8.iQuant = Data->iQuant;  
                 Data8.iEdgedWidth = Data->iEdgedWidth;  
1077                  Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);                  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);                  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);                  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);                  Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1081    
1082                    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                            for (i = 0; i < 4; i++) {
1088                                    sumx += mv[i].x / div;
1089                                    sumy += mv[i].y / div;
1090                            }
1091    
1092                            Data->iMinSAD[1] += ChromaSAD(  (sumx >> 3) + roundtab_76[sumx & 0xf],
1093                                                                                            (sumy >> 3) + roundtab_76[sumy & 0xf], Data);
1094                    }
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) ||
# Line 819  Line 1104 
1104                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                          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->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] = Data->currentMV[0];                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = Data->iMinSAD[0];
   
                 pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =  
                         pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];  
1109    
1110                    if(Data->qpel) {
1111                            pMB->qmvs[0] = pMB->qmvs[1]
1112                                    = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1113                            pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predMV.x;
1114                            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;                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1117                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;                  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 = Data->iMinSAD[1] + Data->iMinSAD[2] +                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1123                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1124          }          }
   
1125  }  }
1126    
1127  static void  static void
# Line 846  Line 1134 
1134                  const int block,                  const int block,
1135                  SearchData * const Data)                  SearchData * const Data)
1136  {  {
1137          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          int i = 0;
1138          Data->iMinSAD = OldData->iMinSAD + 1 + block;          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1139          Data->currentMV = OldData->currentMV + 1 + block;          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->iMinSAD) += (Data->lambda8 * i * (*Data->iMinSAD + NEIGH_8X8_BIAS))>>10;
1153    
1154          if (block != 0)          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8|PMV_QUARTERPELREFINE8)) {
1155                  *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *                  if (Data->rrv) i = 2; else i = 1;
                                                                 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));  
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                    Data->Cur = OldData->Cur + i * 8 * ((block&1) + Data->iEdgedWidth*(block>>1));
1163                    Data->qpel_precision = 0;
1164    
1165                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1166                                  pParam->width, pParam->height, OldData->iFcode);                                          pParam->width, pParam->height, Data->iFcode - Data->qpel, 0, Data->rrv);
1167    
1168                  CheckCandidate = CheckCandidate8;                  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 (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(Data);                          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(*(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                    if (Data->qpel && MotionFlags & PMV_QUARTERPELREFINE8) {
1199                                    Data->qpel_precision = 1;
1200                                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1201                                            pParam->width, pParam->height, Data->iFcode, 1, 0);
1202                                    SubpelRefine(Data);
1203                    }
1204            }
1205    
1206            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;          pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1217          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1218          pMB->mvs[block] = *(Data->currentMV);          }
         pMB->sad8[block] =  4 * (*Data->iMinSAD);  
1219    
1220            pMB->mvs[block] = *Data->currentMV;
1221            pMB->sad8[block] = 4 * *Data->iMinSAD;
1222  }  }
1223    
1224  /* B-frames code starts here */  /* 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 929  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 947  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->Ref = pRef + (x + y * Data->iEdgedWidth) * 16;
1296            Data->RefH = pRefH + (x + y * Data->iEdgedWidth) * 16;
1297            Data->RefV = pRefV + (x + y * Data->iEdgedWidth) * 16;
1298            Data->RefHV = pRefHV + (x + y * Data->iEdgedWidth) * 16;
1299    
1300          Data.iMinSAD = &iMinSAD;          Data->predMV = *predMV;
1301          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
1302          Data.iEdgedWidth = iEdgedWidth;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1303          Data.currentMV = &currentMV;                                  pParam->width, pParam->height, iFcode - Data->qpel, 0, 0);
         Data.iMinSAD = &iMinSAD;  
         Data.Ref = pRef + (x + y * iEdgedWidth) * 16;  
         Data.RefH = pRefH + (x + y * iEdgedWidth) * 16;  
         Data.RefV = pRefV + (x + y * iEdgedWidth) * 16;  
         Data.RefHV = pRefHV + (x + y * iEdgedWidth) * 16;  
   
         Data.iQuant = iQuant;  
         Data.iFcode = iFcode;  
         Data.predMV = *predMV;  
   
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,  
                                 pParam->width, pParam->height, iFcode);  
   
         if (!(MotionFlags & PMV_HALFPEL16)) {  
                 Data.min_dx = EVEN(Data.min_dx);  
                 Data.max_dx = EVEN(Data.max_dx);  
                 Data.min_dy = EVEN(Data.min_dy);  
                 Data.max_dy = EVEN(Data.max_dy); } // no-halpel and b-frames. do we need it?  
   
   
         pmv[0] = Data.predMV;  
         PreparePredictionsBF(pmv, x, y, pParam->mb_width,  
                                         pMB, mode_current);  
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            SubpelRefine(Data);
1326    
1327          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          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    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,  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,
# Line 1041  Line 1414 
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 = 266*4096, 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->y + (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->y + (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) ) {
                         || ( 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 )) {  
1456    
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;                          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) {                  if (b_mb->mode != MODE_INTER4V) {
1463                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];                          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];                          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];                          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];                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1467                          break;                          break;
1468                  }                  }
1469          }          }
1470    
1471          if (b_mb->mode == MODE_INTER4V)          CheckCandidate = b_mb->mode == MODE_INTER4V ? CheckCandidateDirect : CheckCandidateDirectno4v;
                 CheckCandidate = CheckCandidateDirect;  
         else CheckCandidate = CheckCandidateDirectno4v;  
   
         (*CheckCandidate)(0, 0, 255, &k, &Data);  
1472    
1473  // skip decision          (*CheckCandidate)(0, 0, 255, &k, Data);
         if (iMinSAD - 2 * lambda_vec16[iQuant] < (int32_t)iQuant * SKIP_THRESH_B) {  
                 //checking chroma. everything copied from MC  
                 //this is not full chroma compensation, only it's fullpel approximation. should work though  
                 int sum, dx, dy, b_dx, b_dy;  
   
                 sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;  
                 dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));  
   
                 sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;  
                 dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));  
   
                 sum = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;  
                 b_dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));  
1474    
1475                  sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;  // initial (fast) skip decision
1476                  b_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));          if (*Data->iMinSAD < pMB->quant * INITIAL_SKIP_THRESH * 2) {
1477                    //possible skip - checking chroma
1478                  sum = sad8bi(pCur->u + 8*x + 8*y*(iEdgedWidth/2),                  SkipDecisionB(pCur, f_Ref, b_Ref, pMB, x, y, Data);
1479                                          f_Ref->u + (y*8 + dy/2) * (iEdgedWidth/2) + x*8 + dx/2,                  if (pMB->mode == MODE_DIRECT_NONE_MV) return *Data->iMinSAD; // skip.
                                         b_Ref->u + (y*8 + b_dy/2) * (iEdgedWidth/2) + x*8 + b_dx/2,  
                                         iEdgedWidth/2);  
                 sum += sad8bi(pCur->v + 8*x + 8*y*(iEdgedWidth/2),  
                                         f_Ref->v + (y*8 + dy/2) * (iEdgedWidth/2) + x*8 + dx/2,  
                                         b_Ref->v + (y*8 + b_dy/2) * (iEdgedWidth/2) + x*8 + b_dx/2,  
                                         iEdgedWidth/2);  
   
                 if ((uint32_t) sum < MAX_CHROMA_SAD_FOR_SKIP * Data.iQuant) {  
                         pMB->mode = MODE_DIRECT_NONE_MV;  
                         return iMinSAD;  
                 }  
1480          }          }
1481    
1482          skip_sad = iMinSAD;          skip_sad = *Data->iMinSAD;
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 1154  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 1199  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          bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;          i = (x + y * fData->iEdgedWidth) * 16;
1562          bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;          bData.bRef = fData->Ref = f_Ref + i;
1563          bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;          bData.bRefH = fData->RefH = f_RefH + i;
1564          bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;          bData.bRefV = fData->RefV = f_RefV + i;
1565          bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;          bData.bRefHV = fData->RefHV = f_RefHV + i;
1566          bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;          bData.Ref = fData->bRef = b_Ref + i;
1567          bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;          bData.RefH = fData->bRefH = b_RefH + i;
1568          bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;          bData.RefV = fData->bRefV = b_RefV + i;
1569            bData.RefHV = fData->bRefHV = b_RefHV + i;
1570          bData.bpredMV = fData.predMV = *f_predMV;  
1571          fData.bpredMV = bData.predMV = *b_predMV;          bData.bpredMV = fData->predMV = *f_predMV;
1572            fData->bpredMV = bData.predMV = *b_predMV;
1573          currentMV[0] = pMB->mvs[0];          fData->currentMV[0] = fData->currentMV[2];
1574          currentMV[1] = pMB->b_mvs[0];  
1575          get_range(&fData.min_dx, &fData.max_dx, &fData.min_dy, &fData.max_dy, x, y, 16, pParam->width, pParam->height, fcode);          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);          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 (currentMV[0].x > fData.max_dx) currentMV[0].x = fData.max_dx;          if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1579          if (currentMV[0].x < fData.min_dx) currentMV[0].x = fData.min_dy;          if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dx;
1580          if (currentMV[0].y > fData.max_dy) currentMV[0].y = fData.max_dx;          if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dy;
1581          if (currentMV[0].y > fData.min_dy) currentMV[0].y = fData.min_dy;          if (fData->currentMV[0].y < fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1582    
1583          if (currentMV[1].x > bData.max_dx) currentMV[1].x = bData.max_dx;          if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1584          if (currentMV[1].x < bData.min_dx) currentMV[1].x = bData.min_dy;          if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dx;
1585          if (currentMV[1].y > bData.max_dy) currentMV[1].y = bData.max_dx;          if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dy;
1586          if (currentMV[1].y > bData.min_dy) currentMV[1].y = bData.min_dy;          if (fData->currentMV[1].y < bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1587    
1588          CheckCandidateInt(currentMV[0].x, currentMV[0].y, 255, &iDirection, &fData);          CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
   
 //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  
1589    
1590    //diamond
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 + 1, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1597                  CheckCandidateInt(i, j + 1, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1598                  CheckCandidateInt(i - 1, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1599                  CheckCandidateInt(i, j - 1, 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);                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1605                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1606                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
# Line 1279  Line 1608 
1608    
1609          } while (!(iDirection));          } while (!(iDirection));
1610    
1611  // two bits are needed to code interpolate mode. we treat the bits just like they were vector's  //qpel refinement
1612          iMinSAD +=  2 * lambda_vec16[iQuant];          if (fData->qpel) {
1613          if (iMinSAD < *best_sad) {                  if (*fData->iMinSAD > *best_sad + 500) return;
1614                  *best_sad = iMinSAD;                  CheckCandidate = CheckCandidateInt;
1615                  pMB->mvs[0] = currentMV[0];                  fData->qpel_precision = bData.qpel_precision = 1;
1616                  pMB->b_mvs[0] = currentMV[1];                  get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, 1, 0);
1617                    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                    fData->currentQMV[1].x = 2 * fData->currentMV[1].x;
1621                    fData->currentQMV[1].y = 2 * fData->currentMV[1].y;
1622                    SubpelRefine(fData);
1623                    if (*fData->iMinSAD > *best_sad + 300) return;
1624                    fData->currentQMV[2] = fData->currentQMV[0];
1625                    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 1306  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 1332  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,                          skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
1718                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,                                                                          b_ref, 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    
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            Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
1816            Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
1817    
1818          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,          pmv[1].x = EVEN(pMB->mvs[0].x);
1819                                  pParam->width, pParam->height, OldData->iFcode);          pmv[1].y = EVEN(pMB->mvs[0].y);
1820            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 (pMB->mode == MODE_INTER4V) {          CheckCandidate32I(0, 0, 255, &i, Data);
                 int dummy;  
                 CheckCandidate8(pMB->mvs[block].x, pMB->mvs[block].y, 0, &dummy, &Data); }  
1825    
1826          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;          if (*Data->iMinSAD > 4 * MAX_SAD00_FOR_SKIP * 4) {
                 else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;  
                         else MainSearchPtr = DiamondSearch;  
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;  
   
   
         pMB->mvs[0].x = EVEN(pMB->mvs[0].x);  
         pMB->mvs[0].y = EVEN(pMB->mvs[0].y);  
         if (pMB->mvs[0].x > Data.max_dx) pMB->mvs[0].x = Data.max_dx; // this is in case iFcode changed  
         if (pMB->mvs[0].x < Data.min_dx) pMB->mvs[0].x = Data.min_dx;  
         if (pMB->mvs[0].y > Data.max_dy) pMB->mvs[0].y = Data.max_dy;  
         if (pMB->mvs[0].y < Data.min_dy) pMB->mvs[0].y = Data.min_dy;  
   
         CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);  
   
         if (pMB->mode == MODE_INTER4V)  
                 for (i = 1; i < 4; i++) { // all four vectors will be used as four predictions for 16x16 search  
                         pMB->mvs[i].x = EVEN(pMB->mvs[i].x);  
                         pMB->mvs[i].y = EVEN(pMB->mvs[i].y);  
                         if (!(make_mask(pMB->mvs, i)))  
                                 CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);  
                 }  
   
         if (MotionFlags & PMV_USESQUARES16)  
                 MainSearchPtr = SquareSearch;  
         else if (MotionFlags & PMV_ADVANCEDDIAMOND16)  
                 MainSearchPtr = AdvDiamondSearch;  
                 else MainSearchPtr = DiamondSearch;  
1873    
1874          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          if (intraCount != 0 && intraCount < 10) // we're right after an I frame
1875                    IntraThresh += 4 * (intraCount - 10) * (intraCount - 10);
1876            else
1877                    if ( 5*(maxIntra - intraCount) < maxIntra) // we're close to maximum. 2 sec when max is 10 sec
1878                            IntraThresh -= (IntraThresh * (maxIntra - 5*(maxIntra - intraCount)))/maxIntra;
1879    
1880          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          InterThresh += 400 * (1 - bCount);
1881            if (InterThresh < 300) InterThresh = 300;
1882    
1883          if (inter4v)          if (sadInit) (*sadInit) ();
                 for(i = 0; i < 4; i++)  
                         Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);  
1884    
1885          if (!(inter4v) ||          for (y = 1; y < pParam->mb_height-1; y += 2) {
1886                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  for (x = 1; x < pParam->mb_width-1; x += 2) {
1887  // INTER MODE                          int i;
1888    
1889                  pMB->mode = MODE_INTER;                          if (bCount == 0) pMBs[x + y * pParam->mb_width].mvs[0] = zeroMV;
                 pMB->mvs[0] = pMB->mvs[1]  
                         = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];  
1890    
1891                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                          MEanalyzeMB(pRef->y, pCurrent->y, x, y, pParam, pMBs, &Data);
                         pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];  
1892    
1893                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                          for (i = 0; i < 4; i++) {
1894                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                                  int dev;
1895          } else {                                  MACROBLOCK *pMB = &pMBs[x+(i&1) + (y+(i>>1)) * pParam->mb_width];
1896  // INTER4V MODE; all other things are already set in Search8hinted                                  if (pMB->sad16 > IntraThresh) {
1897                  pMB->mode = MODE_INTER4V;                                          dev = dev16(pCurrent->y + (x + (i&1) + (y + (i>>1)) * pParam->edged_width) * 16,
1898                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                                                                          pParam->edged_width);
1899                                            if (dev + IntraThresh < pMB->sad16) {
1900                                                    pMB->mode = MODE_INTRA;
1901                                                    if (++intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return I_VOP;
1902          }          }
   
1903  }  }
1904                                    sSAD += pMB->sad16;
 void  
 MotionEstimationHinted( MBParam * const pParam,  
                                                 FRAMEINFO * const current,  
                                                 FRAMEINFO * const reference,  
                                                 const IMAGE * const pRefH,  
                                                 const IMAGE * const pRefV,  
                                                 const IMAGE * const pRefHV)  
 {  
         MACROBLOCK *const pMBs = current->mbs;  
         const IMAGE *const pCurrent = &current->image;  
         const IMAGE *const pRef = &reference->image;  
   
         uint32_t x, y;  
   
         if (sadInit) (*sadInit) ();  
   
         for (y = 0; y < pParam->mb_height; y++) {  
                 for (x = 0; x < pParam->mb_width; x++)  {  
   
                         MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];  
   
 //intra mode is copied from the first pass. At least for the time being  
                         if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;  
   
                         if (!(current->global_flags & XVID_LUMIMASKING)) {  
                                 pMB->dquant = NO_CHANGE;  
                                 pMB->quant = current->quant; }  
   
                         SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,  
                                                         y, current->motion_flags, pMB->quant,  
                                                         current->fcode, pParam, pMBs,  
                                                         current->global_flags & XVID_INTER4V, pMB);  
   
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  static __inline int  }
 MEanalyzeMB (   const uint8_t * const pRef,  
                                 const uint8_t * const pCur,  
                                 const int x,  
                                 const int y,  
                                 const uint32_t iFcode,  
                                 const MBParam * const pParam,  
                                 const MACROBLOCK * const pMBs,  
                                 MACROBLOCK * const pMB)  
 {  
   
         const int32_t iEdgedWidth = pParam->edged_width;  
         int i, mask;  
         VECTOR currentMV, pmv[3];  
         int32_t iMinSAD = MV_MAX_ERROR;  
         SearchData Data;  
   
         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 + (x + y * iEdgedWidth) * 16;  
         Data.iEdgedWidth = iEdgedWidth;  
         Data.currentMV = &currentMV;  
         Data.iMinSAD = &iMinSAD;  
         Data.Ref = pRef + (x + iEdgedWidth*y)*16;  
         Data.iQuant = 2;  
         Data.iFcode = iFcode;  
   
         CheckCandidate = CheckCandidate16no4vI;  
   
         pmv[1].x = EVEN(pMB->mvs[0].x);  
         pmv[1].y = EVEN(pMB->mvs[0].y);  
         pmv[0].x = EVEN(Data.predMV.x);  
         pmv[0].y = EVEN(Data.predMV.y);  
         pmv[2].x = pmv[2].y = 0;  
   
         CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, &Data);  
         if (!(mask = make_mask(pmv, 1)))  
                 CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, &Data);  
         if (!(mask = make_mask(pmv, 2)))  
                 CheckCandidate16no4vI(0, 0, mask, &i, &Data);  
1915    
1916          DiamondSearch(currentMV.x, currentMV.y, &Data, i);  static void
1917    CheckGMC(int x, int y, const int dir, int * iDirection,
1918                    const MACROBLOCK * const pMBs, uint32_t * bestcount, VECTOR * GMC,
1919                    const MBParam * const pParam)
1920    {
1921            uint32_t mx, my, a, count = 0;
1922    
1923          pMB->mvs[0] = pMB->mvs[1]          for (my = 1; my < pParam->mb_height-1; my++)
1924                          = pMB->mvs[2] = pMB->mvs[3] = currentMV; // all, for future get_pmv()                  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          return iMinSAD;          if (count > *bestcount) {
1934                    *bestcount = count;
1935                    *iDirection = dir;
1936                    GMC->x = x; GMC->y = y;
1937            }
1938  }  }
1939    
 #define INTRA_THRESH    1350  
 #define INTER_THRESH    900  
1940    
1941  int  static VECTOR
1942  MEanalysis(     const IMAGE * const pRef,  GlobalMotionEst(const MACROBLOCK * const pMBs, const MBParam * const pParam, const uint32_t iFcode)
                         const IMAGE * const pCurrent,  
                         MBParam * const pParam,  
                         MACROBLOCK * const pMBs,  
                         const uint32_t iFcode)  
1943  {  {
         uint32_t x, y, intra = 0;  
         int sSAD = 0;  
1944    
1945          if (sadInit) (*sadInit) ();          uint32_t count, bestcount = 0;
1946            int x, y;
1947            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          for (y = 0; y < pParam->mb_height-1; y++) {          min_x = min_y = -32<<iFcode;
1953                  for (x = 0; x < pParam->mb_width; x++) {          max_x = max_y = 32<<iFcode;
                         int sad, dev;  
1954    
1955                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];  //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                          sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,                                                  if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
1968                                                                  iFcode, pParam, pMBs, pMB);                                                          continue;
1969    
1970                          if ( x != 0 && y != 0 && x != pParam->mb_width-1 ) { //no edge macroblocks, they just don't work                                                  mv = pMB->mvs[0];
1971                                  if (sad > INTRA_THRESH) {                                                  if ( ABS(mv.x - x) <= step && ABS(mv.y - y) <= step )   /* GMC translation is always halfpel-res */
1972                                          dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                                          count++;
                                                                   pParam->edged_width);  
                                         if (dev + INTRA_THRESH < sad) intra++;  
                                         if (intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame  
1973                                  }                                  }
1974                                  sSAD += sad;                                  if (count >= bestcount) { bestcount = count; gmc.x = x; gmc.y = y; }
1975                          }                          }
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                  }                  }
1981    
1982            if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10)
1983                    gmc.x = gmc.y = 0; //no camara pan, no GMC
1984    
1985    // step2: let's refine camera panning using gradiend-descent approach
1986    // TODO: more warping points may be evaluated here (like in interpolate mode search - two vectors in one diamond)
1987            bestcount = 0;
1988            CheckGMC(gmc.x, gmc.y, 255, &iDirection, pMBs, &bestcount, &gmc, pParam);
1989            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            } while (iDirection);
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          }          }
         sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);  
         if (sSAD > INTER_THRESH ) return 1; //P frame  
         emms();  
         return 0; // B frame  
2003    
2004            return gmc;
2005  }  }

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

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