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

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

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