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

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

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

revision 530, Mon Sep 23 20:36:02 2002 UTC revision 661, Tue Nov 19 13:43:00 2002 UTC
# Line 37  Line 37 
37  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
38  #include "../global.h"  #include "../global.h"
39  #include "../utils/timer.h"  #include "../utils/timer.h"
40    #include "../image/interpolate8x8.h"
41  #include "motion_est.h"  #include "motion_est.h"
42  #include "motion.h"  #include "motion.h"
43  #include "sad.h"  #include "sad.h"
44    #include "../utils/emms.h"
45    
46  #define INITIAL_SKIP_THRESH     (10)  #define INITIAL_SKIP_THRESH     (10)
47  #define FINAL_SKIP_THRESH       (50)  #define FINAL_SKIP_THRESH       (50)
48  #define MAX_SAD00_FOR_SKIP      (20)  #define MAX_SAD00_FOR_SKIP      (20)
49  #define MAX_CHROMA_SAD_FOR_SKIP (18)  #define MAX_CHROMA_SAD_FOR_SKIP (22)
50  #define SKIP_THRESH_B (10)  #define SKIP_THRESH_B (25)
51    
52  #define CHECK_CANDIDATE(X,Y,D) { \  #define CHECK_CANDIDATE(X,Y,D) { \
53  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }
54    
55  #define iDiamondSize 2  #define GET_REFERENCE(X, Y, REF) { \
56            switch ( (((X)&1)<<1) + ((Y)&1) ) \
57            { \
58                    case 0 : REF = (uint8_t *)data->Ref + (X)/2 + ((Y)/2)*(data->iEdgedWidth); break; \
59                    case 1 : REF = (uint8_t *)data->RefV + (X)/2 + (((Y)-1)/2)*(data->iEdgedWidth); break; \
60                    case 2 : REF = (uint8_t *)data->RefH + ((X)-1)/2 + ((Y)/2)*(data->iEdgedWidth); break; \
61                    default : REF = (uint8_t *)data->RefHV + ((X)-1)/2 + (((Y)-1)/2)*(data->iEdgedWidth); break; \
62            } \
63    }
64    // I hate those macros :/
65    #define GET_REFERENCE2(X, Y, REF) { \
66            switch ( (((X)&1)<<1) + ((Y)&1) ) \
67            { \
68                    case 0 : REF = (uint8_t *)data->bRef + (X)/2 + ((Y)/2)*(data->iEdgedWidth); break; \
69                    case 1 : REF = (uint8_t *)data->bRefV + (X)/2 + (((Y)-1)/2)*(data->iEdgedWidth); break; \
70                    case 2 : REF = (uint8_t *)data->bRefH + ((X)-1)/2 + ((Y)/2)*(data->iEdgedWidth); break; \
71                    default : REF = (uint8_t *)data->bRefHV + ((X)-1)/2 + (((Y)-1)/2)*(data->iEdgedWidth); break; \
72            } \
73    }
74    
75    
76  //FILE * debug;  #define iDiamondSize 2
77    
78  static __inline int  static __inline int
79  d_mv_bits(int x, int y, const uint32_t iFcode)  d_mv_bits(int x, int y, const uint32_t iFcode)
# Line 79  Line 100 
100          return xb + yb;          return xb + yb;
101  }  }
102    
103  /* CHACK_CANDIATE FUNCTIONS START */  static int32_t
104    ChromaSAD(int dx, int dy, const SearchData * const data)
105    {
106            int sad;
107            dx = (dx >> 1) + roundtab_79[dx & 0x3];
108            dy = (dy >> 1) + roundtab_79[dy & 0x3];
109    
110            switch (((dx & 1) << 1) + (dy & 1))     { // ((dx%2)?2:0)+((dy%2)?1:0)
111                    case 0:
112                            sad = sad8(data->CurU, data->RefCU + (dy/2) * (data->iEdgedWidth/2) + dx/2, data->iEdgedWidth/2);
113                            sad += sad8(data->CurV, data->RefCV + (dy/2) * (data->iEdgedWidth/2) + dx/2, data->iEdgedWidth/2);
114                            break;
115                    case 1:
116                            dx = dx / 2; dy = (dy - 1) / 2;
117                            sad = sad8bi(data->CurU, data->RefCU + dy * (data->iEdgedWidth/2) + dx, data->RefCU + (dy+1) * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2);
118                            sad += sad8bi(data->CurV, data->RefCV + dy * (data->iEdgedWidth/2) + dx, data->RefCV + (dy+1) * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2);
119                            break;
120                    case 2:
121                            dx = (dx - 1) / 2; dy = dy / 2;
122                            sad = sad8bi(data->CurU, data->RefCU + dy * (data->iEdgedWidth/2) + dx, data->RefCU + dy * (data->iEdgedWidth/2) + dx+1, data->iEdgedWidth/2);
123                            sad += sad8bi(data->CurV, data->RefCV + dy * (data->iEdgedWidth/2) + dx, data->RefCV + dy * (data->iEdgedWidth/2) + dx+1, data->iEdgedWidth/2);
124                            break;
125                    default:
126                            dx = (dx - 1) / 2; dy = (dy - 1) / 2;
127                            interpolate8x8_halfpel_hv(data->RefQ,
128                                                                             data->RefCU + dy * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2,
129                                                                             data->rounding);
130                            sad = sad8(data->CurU, data->RefQ, data->iEdgedWidth/2);
131                            interpolate8x8_halfpel_hv(data->RefQ,
132                                                                             data->RefCV + dy * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2,
133                                                                             data->rounding);
134                            sad += sad8(data->CurV, data->RefQ, data->iEdgedWidth/2);
135                            break;
136            }
137            return sad;
138    }
139    
140    
141    /* CHECK_CANDIATE FUNCTIONS START */
142    
143    
144  static void  static void
145  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)
146  {  {
         int32_t * const sad = data->temp;  
 //      static int32_t sad[5];  
147          int t;          int t;
148          const uint8_t * Reference;          const uint8_t * Reference;
149    
# Line 99  Line 157 
157                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;
158          }          }
159    
160          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, sad+1);          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
161    
162          t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          if (data->qpel) t = d_mv_bits(2*x - data->predQMV.x, 2*y - data->predQMV.y, data->iFcode);
163          data->temp[0] += lambda_vec16[data->iQuant] * t;          else t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
164          data->temp[1] += lambda_vec8[data->iQuant] * t;  
165            data->temp[0] += (data->lambda16 * t * data->temp[0])/1000;
166            data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))/100;
167    
168            if (data->chroma) data->temp[0] += ChromaSAD(x, y, data);
169    
170          if (data->temp[0] < data->iMinSAD[0]) {          if (data->temp[0] < data->iMinSAD[0]) {
171                  data->iMinSAD[0] = data->temp[0];                  data->iMinSAD[0] = data->temp[0];
# Line 138  Line 200 
200                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;
201          }          }
202    
203          sad = lambda_vec16[data->iQuant] *          sad = sad16(data->Cur, Reference, data->iEdgedWidth, MV_MAX_ERROR);
204                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          if (data->qpel) //only to be used in b-frames' ME
205          sad += sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);                  sad += (data->lambda16 * d_mv_bits(2*x - data->predMV.x, 2*y - data->predMV.y, data->iFcode) * sad)/1000;
206            else
207                    sad += (data->lambda16 * d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode) * sad)/1000;
208    
209            if (sad < *(data->iMinSAD)) {
210                    *(data->iMinSAD) = sad;
211                    data->currentMV[0].x = x; data->currentMV[0].y = y;
212                    *dir = Direction; }
213    }
214    
215    static void
216    CheckCandidate16_qpel(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
217    
218    // CheckCandidate16 variant which expects x and y in quarter pixel resolution
219    // Important: This is no general usable routine! x and y must be +/-1 (qpel resolution!)
220    // around currentMV!
221    {
222            int t;
223            uint8_t * Reference = (uint8_t *)data->RefQ;
224            const uint8_t *ref1, *ref2, *ref3, *ref4;
225            VECTOR halfpelMV = *(data->currentMV);
226    
227            int32_t iEdgedWidth = data->iEdgedWidth;
228            uint32_t rounding = data->rounding;
229    
230            if (( x > data->max_dx) || ( x < data->min_dx)
231                    || ( y > data->max_dy) || (y < data->min_dy)) return;
232    
233            GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1); // this refenrence is used in all cases
234            switch( ((x&1)<<1) + (y&1) )
235            {
236            case 0: // pure halfpel position - shouldn't happen during a refinement step
237                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, Reference);
238                    break;
239    
240            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
241                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
242                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
243                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding);
244                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding);
245                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding);
246                    break;
247    
248            case 2: // x qpel, y halfpel - left or right during qpel refinement
249                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref2);
250                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
251                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding);
252                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding);
253                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding);
254                    break;
255    
256            default: // x and y in qpel resolution - the "corners" (top left/right and
257                             // bottom left/right) during qpel refinement
258                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
259                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref3);
260                    GET_REFERENCE(x - halfpelMV.x, y - halfpelMV.y, ref4);
261    
262                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
263                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
264                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
265                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
266                    break;
267            }
268    
269            data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp+1);
270    
271            t = d_mv_bits(x - data->predQMV.x, y - data->predQMV.y, data->iFcode);
272            data->temp[0] += (data->lambda16 * t * data->temp[0])/1000;
273            data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))/100;
274    
275            if (data->chroma)
276                    data->temp[0] += ChromaSAD(x/2, y/2, data);
277    
278            if (data->temp[0] < data->iMinSAD[0]) {
279                    data->iMinSAD[0] = data->temp[0];
280                    data->currentQMV[0].x = x; data->currentQMV[0].y = y;
281            /*      *dir = Direction;*/ }
282    
283            if (data->temp[1] < data->iMinSAD[1]) {
284                    data->iMinSAD[1] = data->temp[1]; data->currentQMV[1].x = x; data->currentQMV[1].y = y; }
285            if (data->temp[2] < data->iMinSAD[2]) {
286                    data->iMinSAD[2] = data->temp[2]; data->currentQMV[2].x = x; data->currentQMV[2].y = y; }
287            if (data->temp[3] < data->iMinSAD[3]) {
288                    data->iMinSAD[3] = data->temp[3]; data->currentQMV[3].x = x; data->currentQMV[3].y = y; }
289            if (data->temp[4] < data->iMinSAD[4]) {
290                    data->iMinSAD[4] = data->temp[4]; data->currentQMV[4].x = x; data->currentQMV[4].y = y; }
291    }
292    
293    static void
294    CheckCandidate16no4v_qpel(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
295    
296    // CheckCandidate16no4v variant which expects x and y in quarter pixel resolution
297    // Important: This is no general usable routine! x and y must be +/-1 (qpel resolution!)
298    // around currentMV!
299    // this function is for B-frames' search only
300    {
301            uint8_t * Reference = (uint8_t *)data->RefQ;
302            const uint8_t *ref1, *ref2, *ref3, *ref4;
303            VECTOR halfpelMV = *(data->currentMV);
304    
305            int32_t iEdgedWidth = data->iEdgedWidth;
306            int32_t sad;
307    
308            if (( x > data->max_dx) || ( x < data->min_dx)
309                    || ( y > data->max_dy) || (y < data->min_dy)) return;
310    
311            GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1); // this refenrence is used in all cases
312            switch( ((x&1)<<1) + (y&1) )
313            {
314            case 0: // pure halfpel position - shouldn't happen during a refinement step
315                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, Reference);
316                    break;
317    
318            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
319                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
320                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, 0);
321                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, 0);
322                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, 0);
323                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, 0);
324                    break;
325    
326            case 2: // x qpel, y halfpel - left or right during qpel refinement
327                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref2);
328                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, 0);
329                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, 0);
330                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, 0);
331                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, 0);
332                    break;
333    
334            default: // x and y in qpel resolution - the "corners" (top left/right and
335                             // bottom left/right) during qpel refinement
336                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
337                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref3);
338                    GET_REFERENCE(x - halfpelMV.x, y - halfpelMV.y, ref4);
339    
340                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, 0);
341                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, 0);
342                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, 0);
343                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, 0);
344                    break;
345            }
346    
347            sad = sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);
348            sad += (data->lambda16 * d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode) * sad)/1000;
349    
350            if (sad < data->iMinSAD[0]) {
351                    data->iMinSAD[0] = sad;
352                    data->currentQMV[0].x = x; data->currentQMV[0].y = y;
353            /*      *dir = Direction;*/ }
354    }
355    
356    static void
357    CheckCandidate16no4vI(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
358    {
359    // maximum speed - for P/B/I decision
360            int32_t sad;
361    
362            if (( x > data->max_dx) || ( x < data->min_dx)
363                    || ( y > data->max_dy) || (y < data->min_dy)) return;
364    
365            sad = sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),
366                                            data->iEdgedWidth, 256*4096);
367    
368          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
369                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 148  Line 371 
371                  *dir = Direction; }                  *dir = Direction; }
372  }  }
373    
374    
375  static void  static void
376  CheckCandidateInt(const int xf, const int yf, const int Direction, int * const dir, const SearchData * const data)  CheckCandidateInt(const int xf, const int yf, const int Direction, int * const dir, const SearchData * const data)
377  {  {
# Line 173  Line 397 
397                  default : ReferenceB = data->bRefHV + (xb-1)/2 + ((yb-1)/2)*(data->iEdgedWidth); break;                  default : ReferenceB = data->bRefHV + (xb-1)/2 + ((yb-1)/2)*(data->iEdgedWidth); break;
398          }          }
399    
400          sad = lambda_vec16[data->iQuant] *          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
                         ( d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode) +  
                           d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode) );  
401    
402          sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);          if (data->qpel)
403                    sad += (data->lambda16 *
404                            ( d_mv_bits(2*xf - data->predMV.x, 2*yf - data->predMV.y, data->iFcode) +
405                              d_mv_bits(2*xb - data->bpredMV.x, 2*yb - data->bpredMV.y, data->iFcode)) * sad)/1000;
406            else
407                    sad += (data->lambda16 *
408                            ( d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode) +
409                              d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode)) * sad)/1000;
410    
411          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
412                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 185  Line 414 
414                  *dir = Direction; }                  *dir = Direction; }
415  }  }
416    
417    
418  static void  static void
419  CheckCandidateDirect(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidateInt_qpel(const int xf, const int yf, const int Direction, int * const dir, const SearchData * const data)
420  {  {
421    // CheckCandidateInt variant which expects x and y in quarter pixel resolution
422    
423          int32_t sad;          int32_t sad;
424            const int xb = data->currentQMV[1].x;
425            const int yb = data->currentQMV[1].y;
426            uint8_t * ReferenceF = (uint8_t *)data->RefQ;
427            uint8_t * ReferenceB = (uint8_t *)data->RefQ + 16;
428            const uint8_t *ref1, *ref2, *ref3, *ref4;
429            VECTOR halfpelMV;
430            const int32_t iEdgedWidth = data->iEdgedWidth;
431    
432            if (( xf > data->max_dx) || ( xf < data->min_dx)
433                    || ( yf > data->max_dy) || (yf < data->min_dy)) return;
434    
435            halfpelMV.x = xf/2; //forward first
436            halfpelMV.y = yf/2;
437            GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1); // this reference is used in all cases
438            switch( ((xf&1)<<1) + (yf&1) )
439            {
440            case 0: // pure halfpel position - shouldn't happen during a refinement step
441                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ReferenceF);
442                    break;
443    
444            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
445                    GET_REFERENCE(halfpelMV.x, yf - halfpelMV.y, ref2);
446                    interpolate8x8_avg2(ReferenceF, ref1, ref2, iEdgedWidth, 0);
447                    interpolate8x8_avg2(ReferenceF+8, ref1+8, ref2+8, iEdgedWidth, 0);
448                    interpolate8x8_avg2(ReferenceF+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, 0);
449                    interpolate8x8_avg2(ReferenceF+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, 0);
450                    break;
451    
452            case 2: // x qpel, y halfpel - left or right during qpel refinement
453                    GET_REFERENCE(xf - halfpelMV.x, halfpelMV.y, ref2);
454                    interpolate8x8_avg2(ReferenceF, ref1, ref2, iEdgedWidth, 0);
455                    interpolate8x8_avg2(ReferenceF+8, ref1+8, ref2+8, iEdgedWidth, 0);
456                    interpolate8x8_avg2(ReferenceF+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, 0);
457                    interpolate8x8_avg2(ReferenceF+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, 0);
458                    break;
459    
460            default: // x and y in qpel resolution - the "corners" (top left/right and
461                             // bottom left/right) during qpel refinement
462                    GET_REFERENCE(halfpelMV.x, yf - halfpelMV.y, ref2);
463                    GET_REFERENCE(xf - halfpelMV.x, halfpelMV.y, ref3);
464                    GET_REFERENCE(xf - halfpelMV.x, yf - halfpelMV.y, ref4);
465    
466                    interpolate8x8_avg4(ReferenceF, ref1, ref2, ref3, ref4, iEdgedWidth, 0);
467                    interpolate8x8_avg4(ReferenceF+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, 0);
468                    interpolate8x8_avg4(ReferenceF+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, 0);
469                    interpolate8x8_avg4(ReferenceF+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, 0);
470                    break;
471            }
472    
473            halfpelMV.x = xb/2; //backward
474            halfpelMV.y = yb/2;
475            GET_REFERENCE2(halfpelMV.x, halfpelMV.y, ref1); // this reference is used in all cases
476            switch( ((xb&1)<<1) + (yb&1) )
477            {
478            case 0: // pure halfpel position - shouldn't happen during a refinement step
479                    GET_REFERENCE2(halfpelMV.x, halfpelMV.y, ReferenceB);
480                    break;
481    
482            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
483                    GET_REFERENCE2(halfpelMV.x, yb - halfpelMV.y, ref2);
484                    interpolate8x8_avg2(ReferenceB, ref1, ref2, iEdgedWidth, 0);
485                    interpolate8x8_avg2(ReferenceB+8, ref1+8, ref2+8, iEdgedWidth, 0);
486                    interpolate8x8_avg2(ReferenceB+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, 0);
487                    interpolate8x8_avg2(ReferenceB+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, 0);
488                    break;
489    
490            case 2: // x qpel, y halfpel - left or right during qpel refinement
491                    GET_REFERENCE2(xb - halfpelMV.x, halfpelMV.y, ref2);
492                    interpolate8x8_avg2(ReferenceB, ref1, ref2, iEdgedWidth, 0);
493                    interpolate8x8_avg2(ReferenceB+8, ref1+8, ref2+8, iEdgedWidth, 0);
494                    interpolate8x8_avg2(ReferenceB+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, 0);
495                    interpolate8x8_avg2(ReferenceB+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, 0);
496                    break;
497    
498            default: // x and y in qpel resolution - the "corners" (top left/right and
499                             // bottom left/right) during qpel refinement
500                    GET_REFERENCE2(halfpelMV.x, yb - halfpelMV.y, ref2);
501                    GET_REFERENCE2(xb - halfpelMV.x, halfpelMV.y, ref3);
502                    GET_REFERENCE2(xb - halfpelMV.x, yb - halfpelMV.y, ref4);
503    
504                    interpolate8x8_avg4(ReferenceB, ref1, ref2, ref3, ref4, iEdgedWidth, 0);
505                    interpolate8x8_avg4(ReferenceB+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, 0);
506                    interpolate8x8_avg4(ReferenceB+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, 0);
507                    interpolate8x8_avg4(ReferenceB+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, 0);
508                    break;
509            }
510    
511            sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
512    
513            sad += (data->lambda16 *
514                            ( d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode) +
515                              d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode)) * sad)/1000;
516    
517            if (sad < *(data->iMinSAD)) {
518                    *(data->iMinSAD) = sad;
519                    data->currentQMV->x = xf; data->currentQMV->y = yf;
520                    *dir = Direction; }
521    }
522    
523    static void
524    CheckCandidateDirect(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
525    {
526            int32_t sad = 0;
527          int k;          int k;
528          const uint8_t *ReferenceF;          const uint8_t *ReferenceF;
529          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
# Line 196  Line 531 
531    
532          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
533    
         sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);  
   
534          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
535                  mvs.x = data->directmvF[k].x + x;                  mvs.x = data->directmvF[k].x + x;
536                  b_mvs.x = ((x == 0) ?                  b_mvs.x = ((x == 0) ?
# Line 235  Line 568 
568                  if (sad > *(data->iMinSAD)) return;                  if (sad > *(data->iMinSAD)) return;
569          }          }
570    
571            sad += (data->lambda16 * d_mv_bits(x, y, 1) * sad)/1000;
572    
573            if (sad < *(data->iMinSAD)) {
574                    *(data->iMinSAD) = sad;
575                    data->currentMV->x = x; data->currentMV->y = y;
576                    *dir = Direction; }
577    }
578    
579    
580    static void
581    CheckCandidateDirect_qpel(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
582    {
583            int32_t sad = 0;
584            int k;
585            VECTOR mvs, b_mvs, halfpelMV;
586            const uint8_t *ref1, *ref2, *ref3, *ref4;
587            uint8_t *ReferenceF, *ReferenceB;
588            const uint32_t iEdgedWidth = data->iEdgedWidth;
589    
590            if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
591    
592            for (k = 0; k < 4; k++) {
593                    ReferenceF = (uint8_t *)data->RefQ;
594                    ReferenceB = (uint8_t *)data->RefQ + 64;
595    
596                    mvs.x = data->directmvF[k].x + x;
597                    b_mvs.x = ((x == 0) ?
598                            data->directmvB[k].x
599                            : mvs.x - data->referencemv[k].x);
600    
601                    mvs.y = data->directmvF[k].y + y;
602                    b_mvs.y = ((y == 0) ?
603                            data->directmvB[k].y
604                            : mvs.y - data->referencemv[k].y);
605    
606                    if (( mvs.x > data->max_dx ) || ( mvs.x < data->min_dx )
607                            || ( mvs.y > data->max_dy ) || ( mvs.y < data->min_dy )
608                            || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )
609                            || ( b_mvs.y > data->max_dy ) || ( b_mvs.y < data->min_dy )) return;
610    
611                    halfpelMV.x = mvs.x/2; //forward first
612                    halfpelMV.y = mvs.y/2;
613                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1); // this reference is used in all cases
614                    switch( ((mvs.x&1)<<1) + (mvs.y&1) ) {
615                    case 0: // pure halfpel position
616                            GET_REFERENCE(halfpelMV.x + 16*(k&1), halfpelMV.y + 16*(k>>1), ReferenceF);
617                            break;
618    
619                    case 1: // x halfpel, y qpel - top or bottom during qpel refinement
620                            GET_REFERENCE(halfpelMV.x, mvs.y - halfpelMV.y, ref2);
621                            interpolate8x8_avg2(ReferenceF, ref1+8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
622                                                            ref2+ 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth), iEdgedWidth, 0);
623                            break;
624    
625                    case 2: // x qpel, y halfpel - left or right during qpel refinement
626                            GET_REFERENCE(mvs.x - halfpelMV.x, halfpelMV.y, ref2);
627                            interpolate8x8_avg2(ReferenceF, ref1 + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
628                                                            ref2 + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth), iEdgedWidth, 0);
629                            break;
630    
631                    default: // x and y in qpel resolution - the "corners" (top left/right and
632                                     // bottom left/right) during qpel refinement
633                            GET_REFERENCE(halfpelMV.x, mvs.y - halfpelMV.y, ref2);
634                            GET_REFERENCE(mvs.x - halfpelMV.x, halfpelMV.y, ref3);
635                            GET_REFERENCE(mvs.x - halfpelMV.x, mvs.y - halfpelMV.y, ref4);
636                            interpolate8x8_avg4(ReferenceF, ref1 + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
637                                                                    ref2 + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
638                                                                    ref3 + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
639                                                                    ref4 + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth), iEdgedWidth, 0);
640                            break;
641                    }
642    
643                    halfpelMV.x = b_mvs.x/2;
644                    halfpelMV.y = b_mvs.y/2;
645                    GET_REFERENCE2(halfpelMV.x, halfpelMV.y, ref1); // this reference is used in most cases
646                    switch( ((b_mvs.x&1)<<1) + (b_mvs.y&1) ) {
647                    case 0: // pure halfpel position
648                            GET_REFERENCE2(halfpelMV.x + 16*(k&1), halfpelMV.y + 16*(k>>1), ReferenceB);
649                            break;
650    
651                    case 1: // x halfpel, y qpel - top or bottom during qpel refinement
652                            GET_REFERENCE2(halfpelMV.x, b_mvs.y - halfpelMV.y, ref2);
653                            interpolate8x8_avg2(ReferenceB, ref1+8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
654                                                                    ref2+ 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth), iEdgedWidth, 0);
655                            break;
656    
657                    case 2: // x qpel, y halfpel - left or right during qpel refinement
658                            GET_REFERENCE2(b_mvs.x - halfpelMV.x, halfpelMV.y, ref2);
659                            interpolate8x8_avg2(ReferenceB, ref1 + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
660                                                                    ref2 + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth), iEdgedWidth, 0);
661                            break;
662    
663                    default: // x and y in qpel resolution - the "corners" (top left/right and
664                                     // bottom left/right) during qpel refinement
665                            GET_REFERENCE2(halfpelMV.x, b_mvs.y - halfpelMV.y, ref2);
666                            GET_REFERENCE2(b_mvs.x - halfpelMV.x, halfpelMV.y, ref3);
667                            GET_REFERENCE2(b_mvs.x - halfpelMV.x, b_mvs.y - halfpelMV.y, ref4);
668                            interpolate8x8_avg4(ReferenceB, ref1 + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
669                                                                    ref2 + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
670                                                                    ref3 + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
671                                                                    ref4 + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth), iEdgedWidth, 0);
672                            break;
673                    }
674    
675                    sad += sad8bi(data->Cur + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
676                                                    ReferenceF,
677                                                    ReferenceB,
678                                                    data->iEdgedWidth);
679                    if (sad > *(data->iMinSAD)) return;
680            }
681    
682            sad += (data->lambda16 * d_mv_bits(x, y, 1) * sad)/1000;
683    
684            if (sad < *(data->iMinSAD)) {
685                    *(data->iMinSAD) = sad;
686                    data->currentMV->x = x; data->currentMV->y = y;
687                    *dir = Direction; }
688    }
689    
690    static void
691    CheckCandidateDirectno4v_qpel(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
692    {
693            int32_t sad = 0;
694            VECTOR mvs, b_mvs, halfpelMV;
695            const uint8_t *ref1, *ref2, *ref3, *ref4;
696            const uint32_t iEdgedWidth = data->iEdgedWidth;
697            uint8_t * ReferenceF = (uint8_t *)data->RefQ;
698            uint8_t * ReferenceB = (uint8_t *)data->RefQ + 64;
699    
700            if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
701    
702            mvs.x = data->directmvF[0].x + x;
703            b_mvs.x = ((x == 0) ?
704                            data->directmvB[0].x
705                            : mvs.x - data->referencemv[0].x);
706    
707            mvs.y = data->directmvF[0].y + y;
708            b_mvs.y = ((y == 0) ?
709                            data->directmvB[0].y
710                            : mvs.y - data->referencemv[0].y);
711    
712            if (( mvs.x > data->max_dx ) || ( mvs.x < data->min_dx )
713                            || ( mvs.y > data->max_dy ) || ( mvs.y < data->min_dy )
714                            || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )
715                            || ( b_mvs.y > data->max_dy ) || ( b_mvs.y < data->min_dy )) return;
716    
717            halfpelMV.x = mvs.x/2; //forward first
718            halfpelMV.y = mvs.y/2;
719            GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1); // this reference is used in all cases
720            switch( ((mvs.x&1)<<1) + (mvs.y&1) ) {
721            case 0: // pure halfpel position
722                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ReferenceF);
723                    break;
724    
725            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
726                    GET_REFERENCE(halfpelMV.x, mvs.y - halfpelMV.y, ref2);
727                    interpolate8x8_avg2(ReferenceF, ref1, ref2, iEdgedWidth, 0);
728                    interpolate8x8_avg2(ReferenceF+8, ref1+8, ref2+8, iEdgedWidth, 0);
729                    interpolate8x8_avg2(ReferenceF+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, 0);
730                    interpolate8x8_avg2(ReferenceF+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, 0);
731                    break;
732    
733            case 2: // x qpel, y halfpel - left or right during qpel refinement
734                    GET_REFERENCE(mvs.x - halfpelMV.x, halfpelMV.y, ref2);
735                    interpolate8x8_avg2(ReferenceF, ref1, ref2, iEdgedWidth, 0);
736                    interpolate8x8_avg2(ReferenceF+8, ref1+8, ref2+8, iEdgedWidth, 0);
737                    interpolate8x8_avg2(ReferenceF+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, 0);
738                    interpolate8x8_avg2(ReferenceF+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, 0);
739                    break;
740    
741            default: // x and y in qpel resolution
742                    GET_REFERENCE(halfpelMV.x, mvs.y - halfpelMV.y, ref2);
743                    GET_REFERENCE(mvs.x - halfpelMV.x, halfpelMV.y, ref3);
744                    GET_REFERENCE(mvs.x - halfpelMV.x, mvs.y - halfpelMV.y, ref4);
745    
746                    interpolate8x8_avg4(ReferenceF, ref1, ref2, ref3, ref4, iEdgedWidth, 0);
747                    interpolate8x8_avg4(ReferenceF+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, 0);
748                    interpolate8x8_avg4(ReferenceF+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, 0);
749                    interpolate8x8_avg4(ReferenceF+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, 0);
750                    break;
751            }
752    
753            halfpelMV.x = b_mvs.x/2; //backward
754            halfpelMV.y = b_mvs.y/2;
755            GET_REFERENCE2(halfpelMV.x, halfpelMV.y, ref1);
756            switch( ((b_mvs.x&1)<<1) + (b_mvs.y&1) )
757            {
758            case 0: // pure halfpel position
759                    GET_REFERENCE2(halfpelMV.x, halfpelMV.y, ReferenceB);
760                    break;
761    
762            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
763                    GET_REFERENCE2(halfpelMV.x, b_mvs.y - halfpelMV.y, ref2);
764                    interpolate8x8_avg2(ReferenceB, ref1, ref2, iEdgedWidth, 0);
765                    interpolate8x8_avg2(ReferenceB+8, ref1+8, ref2+8, iEdgedWidth, 0);
766                    interpolate8x8_avg2(ReferenceB+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, 0);
767                    interpolate8x8_avg2(ReferenceB+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, 0);
768                    break;
769    
770            case 2: // x qpel, y halfpel - left or right during qpel refinement
771                    GET_REFERENCE2(b_mvs.x - halfpelMV.x, halfpelMV.y, ref2);
772                    interpolate8x8_avg2(ReferenceB, ref1, ref2, iEdgedWidth, 0);
773                    interpolate8x8_avg2(ReferenceB+8, ref1+8, ref2+8, iEdgedWidth, 0);
774                    interpolate8x8_avg2(ReferenceB+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, 0);
775                    interpolate8x8_avg2(ReferenceB+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, 0);
776                    break;
777    
778            default: // x and y in qpel resolution - the "corners" (top left/right and
779                             // bottom left/right) during qpel refinement
780                    GET_REFERENCE2(halfpelMV.x, b_mvs.y - halfpelMV.y, ref2);
781                    GET_REFERENCE2(b_mvs.x - halfpelMV.x, halfpelMV.y, ref3);
782                    GET_REFERENCE2(b_mvs.x - halfpelMV.x, b_mvs.y - halfpelMV.y, ref4);
783    
784                    interpolate8x8_avg4(ReferenceB, ref1, ref2, ref3, ref4, iEdgedWidth, 0);
785                    interpolate8x8_avg4(ReferenceB+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, 0);
786                    interpolate8x8_avg4(ReferenceB+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, 0);
787                    interpolate8x8_avg4(ReferenceB+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, 0);
788                    break;
789            }
790    
791            sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
792            sad += (data->lambda16 * d_mv_bits(x, y, 1) * sad)/1000;
793    
794          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
795                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
796                  data->currentMV->x = x; data->currentMV->y = y;                  data->currentMV->x = x; data->currentMV->y = y;
797                  *dir = Direction; }                  *dir = Direction; }
798  }  }
799    
800    
801  static void  static void
802  CheckCandidateDirectno4v(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidateDirectno4v(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
803  {  {
# Line 249  Line 806 
806          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
807          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
808    
809          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);  
810    
811          mvs.x = data->directmvF[0].x + x;          mvs.x = data->directmvF[0].x + x;
812          b_mvs.x = ((x == 0) ?          b_mvs.x = ((x == 0) ?
# Line 282  Line 837 
837                  default : ReferenceB = data->bRefHV + (b_mvs.x-1)/2 + ((b_mvs.y-1)/2)*(data->iEdgedWidth); break;                  default : ReferenceB = data->bRefHV + (b_mvs.x-1)/2 + ((b_mvs.y-1)/2)*(data->iEdgedWidth); break;
838          }          }
839    
840          sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
841            sad += (data->lambda16 * d_mv_bits(x, y, 1) * sad)/1000;
842    
843          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
844                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 293  Line 849 
849  static void  static void
850  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)
851  {  {
852          int32_t sad;          int32_t sad; int t;
853          const uint8_t * Reference;          const uint8_t * Reference;
854    
855          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
# Line 308  Line 864 
864          }          }
865    
866          sad = sad8(data->Cur, Reference, data->iEdgedWidth);          sad = sad8(data->Cur, Reference, data->iEdgedWidth);
867          sad += lambda_vec8[data->iQuant] * d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          if (data->qpel) t = d_mv_bits(2 * x - data->predQMV.x, 2 * y - data->predQMV.y, data->iFcode);
868            else t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
869    
870            sad += (data->lambda8 * t * (sad+NEIGH_8X8_BIAS))/100;
871    
872          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
873                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 316  Line 875 
875                  *dir = Direction; }                  *dir = Direction; }
876  }  }
877    
878  /* CHACK_CANDIATE FUNCTIONS END */  static void
879    CheckCandidate8_qpel(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
880    // CheckCandidate8 variant which expects x and y in quarter pixel resolution
881    // Important: This is no general usable routine! x and y must be +/-1 (qpel resolution!)
882    // around currentMV!
883    
884    {
885            int32_t sad;
886            uint8_t *Reference = (uint8_t *) data->RefQ;
887            const uint8_t *ref1, *ref2, *ref3, *ref4;
888            VECTOR halfpelMV = *(data->currentMV);
889    
890            int32_t iEdgedWidth = data->iEdgedWidth;
891            uint32_t rounding = data->rounding;
892    
893            if (( x > data->max_dx) || ( x < data->min_dx)
894                    || ( y > data->max_dy) || (y < data->min_dy)) return;
895    
896            GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
897            switch( ((x&1)<<1) + (y&1) )
898            {
899            case 0: // pure halfpel position - shouldn't happen during a refinement step
900                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, Reference);
901                    break;
902    
903            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
904                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
905    
906                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
907                    break;
908    
909            case 2: // x qpel, y halfpel - left or right during qpel refinement
910                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref2);
911    
912                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
913                    break;
914    
915            default: // x and y in qpel resolution - the "corners" (top left/right and
916                             // bottom left/right) during qpel refinement
917                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
918                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref3);
919                    GET_REFERENCE(x - halfpelMV.x, y - halfpelMV.y, ref4);
920    
921                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
922                    break;
923            }
924    
925            sad = sad8(data->Cur, Reference, data->iEdgedWidth);
926            sad += (data->lambda8 * d_mv_bits(x - data->predQMV.x, y - data->predQMV.y, data->iFcode) * (sad+NEIGH_8X8_BIAS))/100;
927    
928            if (sad < *(data->iMinSAD)) {
929                    *(data->iMinSAD) = sad;
930                    data->currentQMV->x = x; data->currentQMV->y = y;
931                    *dir = Direction; }
932    }
933    
934    /* CHECK_CANDIATE FUNCTIONS END */
935    
936  /* MAINSEARCH FUNCTIONS START */  /* MAINSEARCH FUNCTIONS START */
937    
# Line 484  Line 1099 
1099          CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);          CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);
1100  }  }
1101    
1102    
1103    static void
1104    QuarterpelRefine(const SearchData * const data)
1105    {
1106    /* Perform quarter pixel refinement*/
1107    
1108            VECTOR backupMV = *(data->currentQMV);
1109            int iDirection; //not needed
1110    
1111            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);
1112            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);
1113            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);
1114            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y + 1, 0);
1115    
1116            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y, 0);
1117            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y, 0);
1118    
1119            CHECK_CANDIDATE(backupMV.x, backupMV.y + 1, 0);
1120            CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);
1121    
1122    }
1123    
1124  static __inline int  static __inline int
1125  SkipDecisionP(const IMAGE * current, const IMAGE * reference,  SkipDecisionP(const IMAGE * current, const IMAGE * reference,
1126                                                          const int x, const int y,                                                          const int x, const int y,
# Line 497  Line 1134 
1134          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,
1135                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);
1136          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
1137          sadC += sad8(current->v + x*8 + y*(iEdgedWidth/2)*8,          sadC += sad8(current->v + (x + y*(iEdgedWidth/2))*8,
1138                                          reference->v + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                          reference->v + (x + y*(iEdgedWidth/2))*8, iEdgedWidth/2);
1139          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
1140    
1141          return 1;          return 1;
# Line 508  Line 1145 
1145  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)
1146  {  {
1147          pMB->mode = MODE_NOT_CODED;          pMB->mode = MODE_NOT_CODED;
1148          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = pMB->mv16.x = 0;          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;
1149          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = pMB->mv16.y = 0;          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;
1150    
1151            pMB->qmvs[0].x = pMB->qmvs[1].x = pMB->qmvs[2].x = pMB->qmvs[3].x = 0;
1152            pMB->qmvs[0].y = pMB->qmvs[1].y = pMB->qmvs[2].y = pMB->qmvs[3].y = 0;
1153    
1154          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;
1155  }  }
1156    
# Line 530  Line 1171 
1171    
1172          uint32_t x, y;          uint32_t x, y;
1173          uint32_t iIntra = 0;          uint32_t iIntra = 0;
1174          int32_t InterBias;          int32_t InterBias, quant = current->quant, sad00;
1175            uint8_t *qimage;
1176    
1177            // some pre-initialized thingies for SearchP
1178            int32_t temp[5];
1179            VECTOR currentMV[5];
1180            VECTOR currentQMV[5];
1181            int32_t iMinSAD[5];
1182            SearchData Data;
1183            Data.iEdgedWidth = pParam->edged_width;
1184            Data.currentMV = currentMV;
1185            Data.currentQMV = currentQMV;
1186            Data.iMinSAD = iMinSAD;
1187            Data.temp = temp;
1188            Data.iFcode = current->fcode;
1189            Data.rounding = pParam->m_rounding_type;
1190            Data.qpel = pParam->m_quarterpel;
1191            Data.chroma = current->global_flags & XVID_ME_COLOUR;
1192    
1193            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
1194                    return 1; // allocate some mem for qpel interpolated blocks
1195                                      // somehow this is dirty since I think we shouldn't use malloc outside
1196                                      // encoder_create() - so please fix me!
1197            Data.RefQ = qimage;
1198          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
1199    
1200          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
1201                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
   
1202                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
1203                          int32_t sad00 =  pMB->sad16  
1204                            pMB->sad16
1205                                  = sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,                                  = sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,
1206                                                          pRef->y + (x + y * pParam->edged_width) * 16,                                                          pRef->y + (x + y * pParam->edged_width) * 16,
1207                                                          pParam->edged_width, pMB->sad8 );                                                          pParam->edged_width, pMB->sad8 );
1208    
1209                            if (Data.chroma) {
1210                                    pMB->sad16 += sad8(pCurrent->u + x*8 + y*(pParam->edged_width/2)*8,
1211                                                                    pRef->u + x*8 + y*(pParam->edged_width/2)*8, pParam->edged_width/2);
1212    
1213                                    pMB->sad16 += sad8(pCurrent->v + (x + y*(pParam->edged_width/2))*8,
1214                                                                    pRef->v + (x + y*(pParam->edged_width/2))*8, pParam->edged_width/2);
1215                            }
1216    
1217                            sad00 = pMB->sad16; //if no gmc; else sad00 = (..)
1218    
1219                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
1220                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
1221                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant;
1222                            } else {
1223                                    if (pMB->dquant != NO_CHANGE) {
1224                                            quant += DQtab[pMB->dquant];
1225                                            if (quant > 31) quant = 31;
1226                                            else if (quant < 1) quant = 1;
1227                                    }
1228                                    pMB->quant = quant;
1229                            }
1230    
1231  //initial skip decision  //initial skip decision
1232    /* no early skip for GMC (global vector = skip vector is unknown!)  */
1233                          if ((pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)                          if (current->coding_type == P_VOP)      { /* no fast SKIP for S(GMC)-VOPs */
1234                                  && (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) ) {                                  if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * INITIAL_SKIP_THRESH)
1235                                  if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {                                          if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
1236                                                  SkipMacroblockP(pMB, sad00);                                                  SkipMacroblockP(pMB, sad00);
1237                                                  continue;                                                  continue;
1238                                  }                                  }
1239                          } else sad00 = 256*4096; // skip not allowed - for final skip decision                          }
1240    
1241                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchP(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
1242                                                  y, current->motion_flags, pMB->quant,                                                  y, current->motion_flags, pMB->quant,
1243                                                  current->fcode, pParam, pMBs, reference->mbs,                                                  &Data, pParam, pMBs, reference->mbs,
1244                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
1245    
1246  /* 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?" */
1247                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)                          if (current->coding_type == P_VOP)      {
1248                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)                                  if ( (pMB->dquant == NO_CHANGE) && (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)
1249                                  { SkipMacroblockP(pMB, sad00); continue; }                                  && ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH) )
1250                                            if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
1251                                                    SkipMacroblockP(pMB, sad00);
1252                                                    continue;
1253                                            }
1254                            }
1255    
1256  /* finally, intra decision */  /* finally, intra decision */
1257    
1258                          InterBias = MV16_INTER_BIAS;                          InterBias = MV16_INTER_BIAS;
1259                          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
1260                          if (y != 0)                          if (y != 0)
1261                                  if ((pMB - pParam->mb_width)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - pParam->mb_width)->mode == MODE_INTRA ) InterBias -= 80;
1262                          if (x != 0)                          if (x != 0)
1263                                  if ((pMB - 1)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - 1)->mode == MODE_INTRA ) InterBias -= 80;
1264    
1265                            if (Data.chroma) InterBias += 50; // to compensate bigger SAD
1266    
1267                          if (InterBias < pMB->sad16)  {                          if (InterBias < pMB->sad16)  {
1268                                  const int32_t deviation =                                  const int32_t deviation =
# Line 582  Line 1270 
1270                                                    pParam->edged_width);                                                    pParam->edged_width);
1271    
1272                                  if (deviation < (pMB->sad16 - InterBias)) {                                  if (deviation < (pMB->sad16 - InterBias)) {
1273                                          if (++iIntra >= iLimit) return 1;                                          if (++iIntra >= iLimit) { free(qimage); return 1; }
1274                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
1275                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
1276                                                  pMB->mvs[3] = zeroMV;                                                  pMB->mvs[3] = zeroMV;
1277                                            pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] =
1278                                                            pMB->qmvs[3] = zeroMV;
1279                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
1280                                                  pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
1281                                  }                                  }
1282                          }                          }
1283                  }                  }
1284          }          }
1285            free(qimage);
1286    
1287            if (current->coding_type == S_VOP)      /* first GMC step only for S(GMC)-VOPs */
1288                    current->GMC_MV = GlobalMotionEst( pMBs, pParam, current->fcode );
1289            else
1290                    current->GMC_MV = zeroMV;
1291    
1292          return 0;          return 0;
1293  }  }
1294    
# Line 601  Line 1298 
1298  static __inline int  static __inline int
1299  make_mask(const VECTOR * const pmv, const int i)  make_mask(const VECTOR * const pmv, const int i)
1300  {  {
1301          int mask = 0xFF, j;          int mask = 255, j;
1302          for (j = 0; j < i; j++) {          for (j = 0; j < i; j++) {
1303                  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
1304                  if (pmv[i].x == pmv[j].x) {                  if (pmv[i].x == pmv[j].x) {
# Line 625  Line 1322 
1322    
1323          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour
1324                  pmv[5].x = EVEN(pmv[3].x);                  pmv[5].x = EVEN(pmv[3].x);
1325                  pmv[5].y = EVEN(pmv[3].y); }                  pmv[5].y = EVEN(pmv[3].y);
1326          else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
1327    
1328          if (x != 0) { pmv[3].x = EVEN(pmv[1].x); pmv[3].y = EVEN(pmv[1].y); }// pmv[3] is left neighbour          if (x != 0) { pmv[3].x = EVEN(pmv[1].x); pmv[3].y = EVEN(pmv[1].y); }// pmv[3] is left neighbour
1329          else pmv[3].x = pmv[3].y = 0;          else pmv[3].x = pmv[3].y = 0;
# Line 644  Line 1341 
1341    
1342          if ((x != iWcount-1) && (y != iHcount-1)) {          if ((x != iWcount-1) && (y != iHcount-1)) {
1343                  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
1344                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y); }                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
1345          else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
1346  }  }
1347    
1348  static void  static void
1349  SearchP(const uint8_t * const pRef,  SearchP(const IMAGE * const pRef,
1350                  const uint8_t * const pRefH,                  const uint8_t * const pRefH,
1351                  const uint8_t * const pRefV,                  const uint8_t * const pRefV,
1352                  const uint8_t * const pRefHV,                  const uint8_t * const pRefHV,
# Line 658  Line 1355 
1355                  const int y,                  const int y,
1356                  const uint32_t MotionFlags,                  const uint32_t MotionFlags,
1357                  const uint32_t iQuant,                  const uint32_t iQuant,
1358                  const uint32_t iFcode,                  SearchData * const Data,
1359                  const MBParam * const pParam,                  const MBParam * const pParam,
1360                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
1361                  const MACROBLOCK * const prevMBs,                  const MACROBLOCK * const prevMBs,
# Line 666  Line 1363 
1363                  MACROBLOCK * const pMB)                  MACROBLOCK * const pMB)
1364  {  {
1365    
         const int32_t iEdgedWidth = pParam->edged_width;  
   
1366          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
1367          int32_t temp[5];          VECTOR pmv[7];
         VECTOR currentMV[5], pmv[7];  
         int32_t psad[4], iMinSAD[5];  
         MainSearchFunc * MainSearchPtr;  
         SearchData Data;  
1368    
1369          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, psad);  //has to be changed to get_pmv(2)()          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()
1370          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,
1371                                  pParam->width, pParam->height, iFcode);                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
1372    
1373          Data.predMV = pmv[0];          Data->predMV = pmv[0];
1374          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
1375          Data.iEdgedWidth = iEdgedWidth;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
1376          Data.currentMV = currentMV;          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1377          Data.iMinSAD = iMinSAD;          Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1378          Data.Ref = pRef + (x + iEdgedWidth*y)*16;  
1379          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16;
1380          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
1381          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
1382          Data.temp = temp;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
1383            Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1384            Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1385    
1386          Data.iQuant = iQuant;          Data->lambda16 = lambda_vec16[iQuant];
1387          Data.iFcode = iFcode;          Data->lambda8 = lambda_vec8[iQuant];
1388    
1389          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
1390                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
1391                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
1392                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
1393                  Data.max_dy = EVEN(Data.max_dy); }                  Data->max_dy = EVEN(Data->max_dy); }
   
         for(i = 0;  i < 5; i++) currentMV[i].x = currentMV[i].y = 0;  
   
         i = d_mv_bits(pmv[0].x, pmv[0].y, iFcode);  
   
         iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;  
         iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;  
         iMinSAD[2] = pMB->sad8[1];  
         iMinSAD[3] = pMB->sad8[2];  
         iMinSAD[4] = pMB->sad8[3];  
1394    
1395          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
1396    
1397            for(i = 0;  i < 5; i++)
1398                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
1399    
1400            if (pParam->m_quarterpel) {
1401                    Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1402                    i = d_mv_bits(Data->predQMV.x, Data->predQMV.y, Data->iFcode);
1403            } else i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);
1404    
1405            Data->iMinSAD[0] = pMB->sad16 + (Data->lambda16 * i * pMB->sad16)/1000;
1406            Data->iMinSAD[1] = pMB->sad8[0] + (Data->lambda8 * i * (pMB->sad8[0]+NEIGH_8X8_BIAS))/100;
1407            Data->iMinSAD[2] = pMB->sad8[1];
1408            Data->iMinSAD[3] = pMB->sad8[2];
1409            Data->iMinSAD[4] = pMB->sad8[3];
1410    
1411          if ((x == 0) && (y == 0)) threshA = 512;          if ((x == 0) && (y == 0)) threshA = 512;
1412          else {          else {
1413                  threshA = psad[0] + 20;                  threshA = Data->temp[0]; // that's when we keep this SAD atm
1414                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
1415                  if (threshA > 1024) threshA = 1024; }                  if (threshA > 1024) threshA = 1024; }
1416    
1417          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,
1418                                          prevMBs + x + y * pParam->mb_width);                                          prevMBs + x + y * pParam->mb_width);
1419    
1420          if (inter4v) CheckCandidate = CheckCandidate16;          if (inter4v || pParam->m_quarterpel || Data->chroma) CheckCandidate = CheckCandidate16;
1421          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
1422    
1423  /* main loop. checking all predictions */  /* main loop. checking all predictions */
1424    
1425          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
1426                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1427                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  (*CheckCandidate)(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1428                  if (iMinSAD[0] < threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1429          }          }
1430    
1431          if ((iMinSAD[0] <= threshA) ||          if ((Data->iMinSAD[0] <= threshA) ||
1432                          (MVequal(currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
1433                          (iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {                          (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {
1434                  inter4v = 0;                  inter4v = 0;
1435                  if (MotionFlags & PMV_QUICKSTOP16) goto PMVfast16_Terminate_without_Refine;          } else {
                 if (MotionFlags & PMV_EARLYSTOP16) {  
                         CheckCandidate = CheckCandidate16no4v; // I sure hope it's faster  
                         goto PMVfast16_Terminate_with_Refine;  
                 }  
         }  
1436    
1437          if (MotionFlags & PMV_USESQUARES16)                  MainSearchFunc * MainSearchPtr;
1438                  MainSearchPtr = SquareSearch;                  if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
1439          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
                 MainSearchPtr = AdvDiamondSearch;  
1440                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1441    
1442          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, iDirection);                  (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1443    
1444  /* extended search, diamond starting in 0,0 and in prediction.  /* extended search, diamond starting in 0,0 and in prediction.
1445          note that this search is/might be done in halfpel positions,          note that this search is/might be done in halfpel positions,
# Line 756  Line 1447 
1447    
1448          if (MotionFlags & PMV_EXTSEARCH16) {          if (MotionFlags & PMV_EXTSEARCH16) {
1449                  int32_t bSAD;                  int32_t bSAD;
1450                  VECTOR startMV = Data.predMV, backupMV = currentMV[0];                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
1451                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?
1452                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);
1453                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1454                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1455    
1456                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1457                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1458                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1459                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1460                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1461                  }                  }
1462    
1463                  backupMV = currentMV[0];                          backupMV = Data->currentMV[0];
1464                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;
1465                  else startMV.x = startMV.y = 0;                  else startMV.x = startMV.y = 0;
1466                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1467                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1468    
1469                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1470                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1471                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1472                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1473                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1474                            }
1475                  }                  }
1476          }          }
1477    
1478  PMVfast16_Terminate_with_Refine:          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1479    
1480          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          for(i = 0; i < 5; i++) {
1481                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1482                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1483            }
1484    
1485            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1486    
1487                    CheckCandidate = CheckCandidate16_qpel;
1488                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1489                                    pParam->width, pParam->height, Data->iFcode, 0);
1490    
1491                    QuarterpelRefine(Data);
1492            }
1493    
1494            if (Data->iMinSAD[0] < (int32_t)iQuant * 30 ) inter4v = 0;
1495            if (inter4v) {
1496                    SearchData Data8;
1497                    Data8.iFcode = Data->iFcode;
1498                    Data8.lambda8 = Data->lambda8;
1499                    Data8.iEdgedWidth = Data->iEdgedWidth;
1500                    Data8.RefQ = Data->RefQ;
1501                    Data8.qpel = Data->qpel;
1502                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1503                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1504                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1505                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1506    
1507  PMVfast16_Terminate_without_Refine:                  if (Data->chroma) {
1508                            int sum, dx, dy;
1509    
1510          if (inter4v)                          if(pParam->m_quarterpel) {
1511                  for(i = 0; i < 4; i++)                                  sum = pMB->qmvs[0].y/2 + pMB->qmvs[1].y/2 + pMB->qmvs[2].y/2 + pMB->qmvs[3].y/2;
1512                          Search8(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                          } else sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1513                            dy = (sum >> 3) + roundtab_76[sum & 0xf];
1514    
1515                            if(pParam->m_quarterpel) {
1516                                    sum = pMB->qmvs[0].x/2 + pMB->qmvs[1].x/2 + pMB->qmvs[2].x/2 + pMB->qmvs[3].x/2;
1517                            } else sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1518                            dx = (sum >> 3) + roundtab_76[sum & 0xf];
1519    
1520                            Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);
1521                    }
1522            }
1523    
1524          if (!(inter4v) ||          if (!(inter4v) ||
1525                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
1526                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1527  // INTER MODE  // INTER MODE
1528                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1529                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1530                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1531    
1532                    pMB->qmvs[0] = pMB->qmvs[1]
1533                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1534    
1535                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1536                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1537    
1538                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1539                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predQMV.x;
1540                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predQMV.y;
1541                    } else {
1542                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1543                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1544                    }
1545          } else {          } else {
1546  // INTER4V MODE; all other things are already set in Search8  // INTER4V MODE; all other things are already set in Search8
1547                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1548                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1549                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1550          }          }
   
1551  }  }
1552    
1553  static void  static void
# Line 820  Line 1557 
1557                  const MBParam * const pParam,                  const MBParam * const pParam,
1558                  MACROBLOCK * const pMB,                  MACROBLOCK * const pMB,
1559                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
1560                  const int block)                  const int block,
1561                    SearchData * const Data)
1562  {  {
1563          SearchData Data;          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1564            Data->currentMV = OldData->currentMV + 1 + block;
1565          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          Data->currentQMV = OldData->currentQMV + 1 + block;
1566          Data.iMinSAD = OldData->iMinSAD + 1 + block;  
1567          Data.currentMV = OldData->currentMV+1+block;          if(pParam->m_quarterpel) {
1568          Data.iFcode = OldData->iFcode;                  Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1569          Data.iQuant = OldData->iQuant;                  if (block != 0) *(Data->iMinSAD) += (Data->lambda8 *
1570                                                                            d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1571          if (block != 0)                                                                                                  Data->currentQMV->y - Data->predQMV.y,
1572                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *                                                                                                  Data->iFcode) * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
1573                                                                  d_mv_bits(      Data.currentMV->x - Data.predMV.x,          } else {
1574                                                                                          Data.currentMV->y - Data.predMV.y,                  Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1575                                                                                          Data.iFcode);                  if (block != 0) *(Data->iMinSAD) += (Data->lambda8 *
1576                                                                            d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1577                                                                                                    Data->currentMV->y - Data->predMV.y,
1578                                                                                                    Data->iFcode) * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
1579            }
1580    
1581          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
1582    
1583                  Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));
1584                  Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));
1585                  Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1586                  Data.RefHV = OldData->RefHV + 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));  
1587    
1588                  get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
                                 pParam->width, pParam->height, OldData->iFcode);  
1589    
1590                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1591                                    pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1592                  CheckCandidate = CheckCandidate8;                  CheckCandidate = CheckCandidate8;
1593    
1594                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & PMV_EXTSEARCH8) {
1595                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1596    
1597                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1598                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1599                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1600                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1601    
1602                          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);     }                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1603    
1604                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                          if(*(Data->iMinSAD) < temp_sad) {
1605                                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1606                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1607                            }
1608                    }
1609    
1610                    if (MotionFlags & PMV_HALFPELREFINE8) {
1611                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1612    
1613                            HalfpelRefine(Data); // perform halfpel refine of current best vector
1614    
1615                            if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1616                                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1617                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1618                            }
1619                    }
1620    
1621                    if(pParam->m_quarterpel) {
1622                            if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1623                                    (MotionFlags & PMV_QUARTERPELREFINE8)) {
1624                            CheckCandidate = CheckCandidate8_qpel;
1625                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1626                                    pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1627                            QuarterpelRefine(Data);
1628                            }
1629                    }
1630            }
1631    
1632            if(pParam->m_quarterpel) {
1633                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predQMV.x;
1634                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predQMV.y;
1635            }
1636            else {
1637                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1638                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1639          }          }
1640    
1641          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;          pMB->mvs[block] = *(Data->currentMV);
1642          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;          pMB->qmvs[block] = *(Data->currentQMV);
1643          pMB->mvs[block] = *(Data.currentMV);  
1644          pMB->sad8[block] =  4 * (*(Data.iMinSAD));          pMB->sad8[block] =  4 * (*Data->iMinSAD);
1645  }  }
1646    
1647  /* B-frames code starts here */  /* B-frames code starts here */
# Line 896  Line 1669 
1669          pmv[2] = ChoosePred(pMB, mode_curr);          pmv[2] = ChoosePred(pMB, mode_curr);
1670          pmv[2].x = EVEN(pmv[2].x); pmv[2].y = EVEN(pmv[2].y);          pmv[2].x = EVEN(pmv[2].x); pmv[2].y = EVEN(pmv[2].y);
1671    
         pmv[3].x = pmv[3].y = 0;  
1672          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour
1673                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);
1674                  pmv[3].x = EVEN(pmv[3].x); pmv[3].y = EVEN(pmv[3].y); }                  pmv[3].x = EVEN(pmv[3].x); pmv[3].y = EVEN(pmv[3].y);
1675            } else pmv[3].x = pmv[3].y = 0;
1676    
1677          if (y != 0) {          if (y != 0) {
1678                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);
# Line 929  Line 1702 
1702                          const IMAGE * const pCur,                          const IMAGE * const pCur,
1703                          const int x, const int y,                          const int x, const int y,
1704                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
1705                          const uint32_t iFcode,                          const uint32_t iFcode,
1706                          const MBParam * const pParam,                          const MBParam * const pParam,
1707                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
1708                          const VECTOR * const predMV,                          const VECTOR * const predMV,
1709                          int32_t * const best_sad,                          int32_t * const best_sad,
1710                          const int32_t mode_current)                          const int32_t mode_current,
1711                            SearchData * const Data)
1712  {  {
1713    
1714          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1715    
1716          int i, iDirection, mask;          int i, iDirection, mask;
1717          VECTOR currentMV, pmv[7];          VECTOR pmv[7];
1718          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1719          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
1720          SearchData Data;          Data->iFcode = iFcode;
   
         Data.iMinSAD = &iMinSAD;  
         Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
         Data.iEdgedWidth = iEdgedWidth;  
         Data.currentMV = &currentMV;  
         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;  
1721    
1722          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,          Data->Ref = pRef + (x + y * iEdgedWidth) * 16;
1723                                  pParam->width, pParam->height, iFcode);          Data->RefH = pRefH + (x + y * iEdgedWidth) * 16;
1724            Data->RefV = pRefV + (x + y * iEdgedWidth) * 16;
1725            Data->RefHV = pRefHV + (x + y * iEdgedWidth) * 16;
1726    
1727          if (!(MotionFlags & PMV_HALFPEL16)) {          Data->predMV = *predMV;
                 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?  
1728    
1729            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1730                                    pParam->width, pParam->height, iFcode, pParam->m_quarterpel);
1731    
1732          pmv[0] = Data.predMV;          pmv[0] = Data->predMV;
1733          PreparePredictionsBF(pmv, x, y, pParam->mb_width,          if (Data->qpel) { pmv[0].x /= 2; pmv[0].y /= 2; }
1734                                          pMB, mode_current);          PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
1735    
1736          currentMV.x = currentMV.y = 0;          Data->currentMV->x = Data->currentMV->y = 0;
1737    
1738          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1739    
1740  // main loop. checking all predictions  // main loop. checking all predictions
1741          for (i = 0; i < 8; i++) {          for (i = 0; i < 8; i++) {
1742                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1743                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1744          }          }
1745    
1746          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 990  Line 1749 
1749                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1750                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1751    
1752          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1753    
1754          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          HalfpelRefine(Data);
1755    
1756            if (Data->qpel) {
1757                    Data->currentQMV->x = 2*Data->currentMV->x;
1758                    Data->currentQMV->y = 2*Data->currentMV->y;
1759                    CheckCandidate = CheckCandidate16no4v_qpel;
1760                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1761                                            pParam->width, pParam->height, iFcode, pParam->m_quarterpel);
1762                    QuarterpelRefine(Data);
1763            }
1764    
1765  // three bits are needed to code backward mode. four for forward  // three bits are needed to code backward mode. four for forward
1766  // we treat the bits just like they were vector's  // we treat the bits just like they were vector's
1767          if (mode_current == MODE_FORWARD) iMinSAD +=  4 * lambda_vec16[iQuant];          if (mode_current == MODE_FORWARD) *Data->iMinSAD +=  4 * Data->lambda16;
1768          else iMinSAD +=  3 * lambda_vec16[iQuant];          else *Data->iMinSAD +=  3 * Data->lambda16;
1769    
1770            if (*Data->iMinSAD < *best_sad) {
1771          if (iMinSAD < *best_sad) {                  *best_sad = *Data->iMinSAD;
                 *best_sad = iMinSAD;  
1772                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1773                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  if (Data->qpel) {
1774                  pMB->pmvs[0].y = currentMV.y - predMV->y;                          pMB->pmvs[0].x = Data->currentQMV->x - predMV->x;
1775                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                          pMB->pmvs[0].y = Data->currentQMV->y - predMV->y;
1776                  else pMB->b_mvs[0] = currentMV;                          if (mode_current == MODE_FORWARD)
1777                                    pMB->qmvs[0] = *Data->currentQMV;
1778                            else
1779                                    pMB->b_qmvs[0] = *Data->currentQMV;
1780                    } else {
1781                            pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1782                            pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1783                    }
1784                    if (mode_current == MODE_FORWARD)
1785                            pMB->mvs[0] = *(Data->currentMV+2) = *Data->currentMV;
1786                    else
1787                            pMB->b_mvs[0] = *(Data->currentMV+1) = *Data->currentMV; //we store currmv for interpolate search
1788    
1789          }          }
1790    
1791  }  }
1792    
1793  static int32_t  static int32_t
1794  SearchDirect(const uint8_t * const f_Ref,  SearchDirect(const IMAGE * const f_Ref,
1795                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1796                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
1797                                  const uint8_t * const f_RefHV,                                  const uint8_t * const f_RefHV,
1798                                  const uint8_t * const b_Ref,                                  const IMAGE * const b_Ref,
1799                                  const uint8_t * const b_RefH,                                  const uint8_t * const b_RefH,
1800                                  const uint8_t * const b_RefV,                                  const uint8_t * const b_RefV,
1801                                  const uint8_t * const b_RefHV,                                  const uint8_t * const b_RefHV,
1802                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1803                                  const int x, const int y,                                  const int x, const int y,
1804                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1805                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1806                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1807                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1808                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1809                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1810                                    SearchData * const Data)
1811    
1812  {  {
1813          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
         int32_t iMinSAD = 0, skip_sad;  
1814          int k;          int k;
         VECTOR currentMV;  
         MainSearchFunc *MainSearchPtr;  
         SearchData Data;  
1815    
1816          Data.iMinSAD = &iMinSAD;          MainSearchFunc *MainSearchPtr;
         Data.Cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;  
         Data.iEdgedWidth = iEdgedWidth;  
         Data.currentMV = &currentMV;  
         Data.iQuant = iQuant;  
         Data.referencemv = b_mb->mvs;  
1817    
1818          Data.Ref= f_Ref + (x + iEdgedWidth*y) * 16;          *Data->iMinSAD = 256*4096;
         Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;  
         Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;  
         Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;  
         Data.bRef = b_Ref + (x + iEdgedWidth*y) * 16;  
         Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;  
         Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;  
         Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;  
 /*  
 //What we do here is a complicated version of CheckCandidateDirect(0,0);  
 get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16, pParam->width, pParam->height, 19);  
1819    
1820  */          Data->Ref = f_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1821          Data.max_dx = 2 * pParam->width - 2 * (x) * 16;          Data->RefH = f_RefH + (x + Data->iEdgedWidth*y) * 16;
1822          Data.max_dy = 2 * pParam->height - 2 * (y) * 16;          Data->RefV = f_RefV + (x + Data->iEdgedWidth*y) * 16;
1823          Data.min_dx = -(2 * 16 + 2 * (x) * 16);          Data->RefHV = f_RefHV + (x + Data->iEdgedWidth*y) * 16;
1824          Data.min_dy = -(2 * 16 + 2 * (y) * 16);          Data->bRef = b_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1825            Data->bRefH = b_RefH + (x + Data->iEdgedWidth*y) * 16;
1826            Data->bRefV = b_RefV + (x + Data->iEdgedWidth*y) * 16;
1827            Data->bRefHV = b_RefHV + (x + Data->iEdgedWidth*y) * 16;
1828    
1829            Data->max_dx = 2 * pParam->width - 2 * (x) * 16;
1830            Data->max_dy = 2 * pParam->height - 2 * (y) * 16;
1831            Data->min_dx = -(2 * 16 + 2 * (x) * 16);
1832            Data->min_dy = -(2 * 16 + 2 * (y) * 16);
1833            if (Data->qpel) { //we measure in qpixels
1834                    Data->max_dx *= 2;
1835                    Data->max_dy *= 2;
1836                    Data->min_dx *= 2;
1837                    Data->min_dy *= 2;
1838                    Data->referencemv = b_mb->qmvs;
1839            } else Data->referencemv = b_mb->mvs;
1840    
1841          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1842                  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);
1843                  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;
1844                  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);
1845                  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;
   
         if (( pMB->mvs[k].x > Data.max_dx ) || ( pMB->mvs[k].x < Data.min_dx )  
                         || ( pMB->mvs[k].y > Data.max_dy ) || ( pMB->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 )) {  
 /*  
                 fprintf(debug, "\nERROR - out of range : vector %d,%d and %d,%d\n", pMB->mvs[k].x, pMB->mvs[k].y,pMB->b_mvs[k].x,pMB->b_mvs[k].y );  
                 fprintf(debug, " range is x: %d..%d y: %d..%d \n", Data.min_dx,Data.max_dx,Data.min_dy,Data.max_dy);  
                 fprintf(debug,"macroblock %d, %d \n", x, y);  
                 fprintf(debug, "direct MV is %d,%d \n", directmv[k].x, directmv[k].y);  
 */  
                 *best_sad = 256*4096; // in that case, we won't use direct mode  
                 pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"  
                 pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;  /* because backwards and interpol might rely on this */  
                 return 0; }  
1846    
1847                    if ( ( pMB->b_mvs[k].x > Data->max_dx ) || ( pMB->b_mvs[k].x < Data->min_dx )
1848                            || ( pMB->b_mvs[k].y > Data->max_dy ) || ( pMB->b_mvs[k].y < Data->min_dy )) {
1849    
1850                            *best_sad = 256*4096; // in that case, we won't use direct mode
1851                            pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
1852                            pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;
1853                            return 0;
1854                    }
1855          if (b_mb->mode != MODE_INTER4V) {          if (b_mb->mode != MODE_INTER4V) {
1856                  iMinSAD = sad16bi(Data.Cur,                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1857                                                  get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,                          pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];
1858                                                                  x, y, 16, &pMB->mvs[0], iEdgedWidth),                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1859                                                  get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1860                                                                  x, y, 16, &pMB->b_mvs[0], iEdgedWidth), iEdgedWidth);                          break;
1861                    }
1862                  Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];          }
1863                  Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];  
1864                  break;          if (Data->qpel) {
1865          }                          if (b_mb->mode == MODE_INTER4V)
1866          iMinSAD += sad8bi(Data.Cur + (k&1)*8 + (k>>1)* 8 * iEdgedWidth,                  CheckCandidate = CheckCandidateDirect_qpel;
1867                                                  get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,                          else CheckCandidate = CheckCandidateDirectno4v_qpel;
1868                                                                  (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->mvs[k], iEdgedWidth),          } else {
1869                                                  get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,                          if (b_mb->mode == MODE_INTER4V) CheckCandidate = CheckCandidateDirect;
1870                                                                  (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->b_mvs[k], iEdgedWidth),                          else CheckCandidate = CheckCandidateDirectno4v;
                                                 iEdgedWidth);  
1871          }          }
1872    
1873            (*CheckCandidate)(0, 0, 255, &k, Data);
1874    
1875  // skip decision  // skip decision
1876          if (iMinSAD < (int32_t)iQuant * SKIP_THRESH_B) {          if (*Data->iMinSAD < pMB->quant * SKIP_THRESH_B) {
1877                    //possible skip - checking chroma. everything copied from MC
1878                    //this is not full chroma compensation, only it's fullpel approximation. should work though
1879                    int sum, dx, dy, b_dx, b_dy;
1880    
1881                    if (Data->qpel) {
1882                            sum = pMB->mvs[0].y/2 + pMB->mvs[1].y/2 + pMB->mvs[2].y/2 + pMB->mvs[3].y/2;
1883                            dy = (sum >> 3) + roundtab_76[sum & 0xf];
1884                            sum = pMB->mvs[0].x/2 + pMB->mvs[1].x/2 + pMB->mvs[2].x/2 + pMB->mvs[3].x/2;
1885                            dx = (sum >> 3) + roundtab_76[sum & 0xf];
1886    
1887                            sum = pMB->b_mvs[0].y/2 + pMB->b_mvs[1].y/2 + pMB->b_mvs[2].y/2 + pMB->b_mvs[3].y/2;
1888                            b_dy = (sum >> 3) + roundtab_76[sum & 0xf];
1889                            sum = pMB->b_mvs[0].x/2 + pMB->b_mvs[1].x/2 + pMB->b_mvs[2].x/2 + pMB->b_mvs[3].x/2;
1890                            b_dx = (sum >> 3) + roundtab_76[sum & 0xf];
1891    
1892                    } else {
1893                            sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1894                            dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1895                            sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1896                            dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1897    
1898                            sum = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;
1899                            b_dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1900                            sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;
1901                            b_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1902                    }
1903                    sum = sad8bi(pCur->u + 8*x + 8*y*(Data->iEdgedWidth/2),
1904                                            f_Ref->u + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1905                                            b_Ref->u + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1906                                            Data->iEdgedWidth/2);
1907                    sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1908                                            f_Ref->v + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1909                                            b_Ref->v + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1910                                            Data->iEdgedWidth/2);
1911    
1912                    if (sum < MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) {
1913                  pMB->mode = MODE_DIRECT_NONE_MV;                  pMB->mode = MODE_DIRECT_NONE_MV;
1914                  return iMinSAD; }                          return *Data->iMinSAD;
1915                    }
1916            }
1917    
1918          skip_sad = iMinSAD;          skip_sad = *Data->iMinSAD;
         iMinSAD += 2 * lambda_vec16[iQuant]; // 2 bits needed to code vector 0,0  
         currentMV.x = currentMV.y = 0;  
         if (b_mb->mode == MODE_INTER4V)  
                 CheckCandidate = CheckCandidateDirect;  
         else CheckCandidate = CheckCandidateDirectno4v;  
1919    
1920  //  DIRECT MODE DELTA VECTOR SEARCH.  //  DIRECT MODE DELTA VECTOR SEARCH.
1921  //      This has to be made more effective, but at the moment I'm happy it's running at all  //      This has to be made more effective, but at the moment I'm happy it's running at all
# Line 1123  Line 1924 
1924                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1925                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1926    
1927          (*MainSearchPtr)(0, 0, &Data, 255);          (*MainSearchPtr)(0, 0, Data, 255);
1928    
1929          HalfpelRefine(&Data);          HalfpelRefine(Data); //or qpel refine, if we're in qpel mode
1930    
1931          iMinSAD +=  1 * lambda_vec16[iQuant]; // one bit is needed to code direct mode. we treat this bit just like it was vector's          *Data->iMinSAD +=  1 * Data->lambda16; // one bit is needed to code direct mode
1932          *best_sad = iMinSAD;          *best_sad = *Data->iMinSAD;
1933    
1934          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1935                  pMB->mode = MODE_DIRECT;                  pMB->mode = MODE_DIRECT;
1936          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1937    
1938          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1939    
1940          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1941                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1942                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = (     (Data->currentMV->x == 0)
1943                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1944                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          :pMB->mvs[k].x - Data->referencemv[k].x);
1945                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1946                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1947                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1948                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1949                    if (Data->qpel) {
1950                            pMB->qmvs[k].x = pMB->mvs[k].x; pMB->mvs[k].x /= 2;
1951                            pMB->b_qmvs[k].x = pMB->b_mvs[k].x; pMB->b_mvs[k].x /= 2;
1952                            pMB->qmvs[k].y = pMB->mvs[k].y; pMB->mvs[k].y /= 2;
1953                            pMB->b_qmvs[k].y = pMB->b_mvs[k].y; pMB->b_mvs[k].y /= 2;
1954                    }
1955    
1956                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1957                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1958                          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];
1959                            pMB->qmvs[3] = pMB->qmvs[2] = pMB->qmvs[1] = pMB->qmvs[0];
1960                            pMB->b_qmvs[3] = pMB->b_qmvs[2] = pMB->b_qmvs[1] = pMB->b_qmvs[0];
1961                          break;                          break;
1962                  }                  }
1963          }          }
1964          return 0;//skip_sad;          return skip_sad;
1965  }  }
1966    
1967    
1968  static __inline void  static __inline void
1969  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const uint8_t * const f_Ref,
1970                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
# Line 1168  Line 1979 
1979                                  const uint32_t fcode,                                  const uint32_t fcode,
1980                                  const uint32_t bcode,                                  const uint32_t bcode,
1981                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1982                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1983                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1984                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1985                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1986                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1987                                    SearchData * const fData)
1988    
1989  {  {
 /* 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". */  
1990    
1991          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
   
1992          int iDirection, i, j;          int iDirection, i, j;
1993          int32_t iMinSAD = 256*4096;          SearchData bData;
         VECTOR currentMV[3];  
         SearchData fData, bData;  
   
1994    
1995          fData.iMinSAD = bData.iMinSAD = &iMinSAD;          *(bData.iMinSAD = fData->iMinSAD) = 4096*256;
1996            bData.Cur = fData->Cur;
1997            fData->iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;
1998            bData.currentMV = fData->currentMV + 1; bData.currentQMV = fData->currentQMV + 1;
1999            bData.lambda16 = fData->lambda16;
2000            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
2001    
2002            bData.bRef = fData->Ref = f_Ref + (x + y * iEdgedWidth) * 16;
2003            bData.bRefH = fData->RefH = f_RefH + (x + y * iEdgedWidth) * 16;
2004            bData.bRefV = fData->RefV = f_RefV + (x + y * iEdgedWidth) * 16;
2005            bData.bRefHV = fData->RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;
2006            bData.Ref = fData->bRef = b_Ref + (x + y * iEdgedWidth) * 16;
2007            bData.RefH = fData->bRefH = b_RefH + (x + y * iEdgedWidth) * 16;
2008            bData.RefV = fData->bRefV = b_RefV + (x + y * iEdgedWidth) * 16;
2009            bData.RefHV = fData->bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;
2010            bData.RefQ = fData->RefQ;
2011    
2012            bData.bpredMV = fData->predMV = *f_predMV;
2013            fData->bpredMV = bData.predMV = *b_predMV;
2014    
2015            fData->currentMV[0] = fData->currentMV[2];
2016            get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, pParam->m_quarterpel);
2017            get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, pParam->m_quarterpel);
2018    
2019            if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
2020            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dy;
2021            if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dx;
2022            if (fData->currentMV[0].y > fData->min_dy) fData->currentMV[0].y = fData->min_dy;
2023    
2024            if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
2025            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dy;
2026            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dx;
2027            if (fData->currentMV[1].y > bData.min_dy) fData->currentMV[1].y = bData.min_dy;
2028    
2029          fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
         fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;  
         fData.currentMV = currentMV; bData.currentMV = currentMV + 1;  
         fData.iQuant = bData.iQuant = iQuant;  
         fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;  
   
   
         bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  
         bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;  
         bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;  
         bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;  
         bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;  
         bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;  
         bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;  
         bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;  
   
         bData.bpredMV = fData.predMV = *f_predMV;  
         fData.bpredMV = bData.predMV = *b_predMV;  
   
   
         currentMV[0] = pMB->mvs[0];  
         currentMV[1] = pMB->b_mvs[0];  
         get_range(&fData.min_dx, &fData.max_dx, &fData.min_dy, &fData.max_dy, x, y, 16, pParam->width, pParam->height, fcode);  
         get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode);  
   
         CheckCandidateInt(currentMV[0].x, currentMV[0].y, 255, &iDirection, &fData);  
2030    
2031  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)
2032    
2033          do {          do {
2034                  iDirection = 255;                  iDirection = 255;
2035                  // forward MV moves                  // forward MV moves
2036                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
2037    
2038                  CheckCandidateInt(i + 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
2039                  CheckCandidateInt(i, j + 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
2040                  CheckCandidateInt(i - 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
2041                  CheckCandidateInt(i, j - 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
2042    
2043                  // backward MV moves                  // backward MV moves
2044                  i = currentMV[1].x; j = currentMV[1].y;                  i = fData->currentMV[1].x; j = fData->currentMV[1].y;
2045                  currentMV[2] = currentMV[0];                  fData->currentMV[2] = fData->currentMV[0];
2046                    CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
2047                  CheckCandidateInt(i + 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
2048                  CheckCandidateInt(i, j + 2, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
2049                  CheckCandidateInt(i - 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, &bData);
                 CheckCandidateInt(i, j - 2, 0, &iDirection, &bData);  
2050    
2051          } while (!(iDirection));          } while (!(iDirection));
2052    
2053  /* halfpel refinement. luckly we can use normal halfpel function for it */          *fData->iMinSAD +=  2 * fData->lambda16; // two bits are needed to code interpolate mode.
   
         if (MotionFlags & PMV_HALFPELREFINE16) {  
                 CheckCandidate = CheckCandidateInt;  
                 HalfpelRefine(&fData);  
                 currentMV[2] = currentMV[0];  
                 HalfpelRefine(&bData);  
         }  
2054    
2055  // two bits are needed to code interpolate mode. we treat the bits just like they were vector's          if (fData->qpel) {
2056          iMinSAD +=  2 * lambda_vec16[iQuant];                  CheckCandidate = CheckCandidateInt_qpel;
2057          if (iMinSAD < *best_sad) {                  get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, 0);
2058                  *best_sad = iMinSAD;                  get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, 0);
2059                  pMB->mvs[0] = currentMV[0];                  fData->currentQMV[2].x = fData->currentQMV[0].x = 2 * fData->currentMV[0].x;
2060                  pMB->b_mvs[0] = currentMV[1];                  fData->currentQMV[2].y = fData->currentQMV[0].y = 2 * fData->currentMV[0].y;
2061                    fData->currentQMV[1].x = 2 * fData->currentMV[1].x;
2062                    fData->currentQMV[1].y = 2 * fData->currentMV[1].y;
2063    //              QuarterpelRefine(fData);
2064                    fData->currentQMV[2] = fData->currentQMV[0];
2065    //              QuarterpelRefine(&bData);
2066            }
2067    
2068            if (*fData->iMinSAD < *best_sad) {
2069                    *best_sad = *fData->iMinSAD;
2070                    pMB->mvs[0] = fData->currentMV[0];
2071                    pMB->b_mvs[0] = fData->currentMV[1];
2072                  pMB->mode = MODE_INTERPOLATE;                  pMB->mode = MODE_INTERPOLATE;
2073                    if (fData->qpel) {
2074                            pMB->qmvs[0] = fData->currentQMV[0];
2075                            pMB->b_qmvs[0] = fData->currentQMV[1];
2076                            pMB->pmvs[1].x = pMB->qmvs[0].x - f_predMV->x;
2077                            pMB->pmvs[1].y = pMB->qmvs[0].y - f_predMV->y;
2078                            pMB->pmvs[0].x = pMB->b_qmvs[0].x - b_predMV->x;
2079                            pMB->pmvs[0].y = pMB->b_qmvs[0].y - b_predMV->y;
2080                    } else {
2081                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;
2082                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;
2083                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;
2084                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;
2085          }          }
2086  }  }
2087    }
2088    
2089  void  void
2090  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
# Line 1277  Line 2098 
2098                                           const IMAGE * const f_refV,                                           const IMAGE * const f_refV,
2099                                           const IMAGE * const f_refHV,                                           const IMAGE * const f_refHV,
2100                                           // backward (future) reference                                           // backward (future) reference
2101                                           const MACROBLOCK * const b_mbs,                                           const FRAMEINFO * const b_reference,
2102                                           const IMAGE * const b_ref,                                           const IMAGE * const b_ref,
2103                                           const IMAGE * const b_refH,                                           const IMAGE * const b_refH,
2104                                           const IMAGE * const b_refV,                                           const IMAGE * const b_refV,
# Line 1287  Line 2108 
2108          int32_t best_sad, skip_sad;          int32_t best_sad, skip_sad;
2109          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;
2110          static const VECTOR zeroMV={0,0};          static const VECTOR zeroMV={0,0};
2111            const MACROBLOCK * const b_mbs = b_reference->mbs;
2112    
2113          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
2114    
2115          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
2116          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
2117            uint8_t * qimage;
2118    
2119          // note: i==horizontal, j==vertical  // some pre-inintialized data for the rest of the search
2120    
2121            SearchData Data;
2122            int32_t iMinSAD;
2123            VECTOR currentMV[3];
2124            VECTOR currentQMV[3];
2125            Data.iEdgedWidth = pParam->edged_width;
2126            Data.currentMV = currentMV; Data.currentQMV = currentQMV;
2127            Data.iMinSAD = &iMinSAD;
2128            Data.lambda16 = lambda_vec16[frame->quant];
2129            Data.qpel = pParam->m_quarterpel;
2130    
2131            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
2132                    return; // allocate some mem for qpel interpolated blocks
2133                                      // somehow this is dirty since I think we shouldn't use malloc outside
2134                                      // encoder_create() - so please fix me!
2135            Data.RefQ = qimage;
2136    
2137            // note: i==horizontal, j==vertical
2138          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
2139    
2140                  f_predMV = b_predMV = zeroMV;   /* prediction is reset at left boundary */                  f_predMV = b_predMV = zeroMV;   /* prediction is reset at left boundary */
# Line 1303  Line 2143 
2143                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;
2144                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;
2145    
2146  /* 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 */
2147                            if (b_reference->coding_type != S_VOP)
2148                          if (b_mb->mode == MODE_NOT_CODED) {                          if (b_mb->mode == MODE_NOT_CODED) {
2149                                  pMB->mode = MODE_NOT_CODED;                                  pMB->mode = MODE_NOT_CODED;
2150                                  continue;                                  continue;
2151                          }                          }
2152    
2153                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
2154                            pMB->quant = frame->quant;
2155    
2156  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
2157          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
2158                            skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
2159                          skip_sad = SearchDirect(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,
                                                                         b_ref->y, b_refH->y, b_refV->y, b_refHV->y,  
2160                                                                          &frame->image,                                                                          &frame->image,
2161                                                                          i, j,                                                                          i, j,
2162                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
2163                                                                          TRB, TRD,                                                                          TRB, TRD,
2164                                                                          pParam,                                                                          pParam,
2165                                                                          pMB, b_mb,                                                                          pMB, b_mb,
2166                                                                          &best_sad);                                                                          &best_sad,
2167                                                                            &Data);
2168    
                         if (!(frame->global_flags & XVID_HALFPEL)) best_sad = skip_sad = 256*4096;  
                         else  
2169                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
2170    
 //                      best_sad = 256*4096; //uncomment to disable Directsearch.  
 //      To disable any other mode, just comment the function call  
   
2171                          // forward search                          // forward search
2172                          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,
2173                                                  &frame->image, i, j,                                                  &frame->image, i, j,
2174                                                  frame->motion_flags,                                                  frame->motion_flags,
2175                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
2176                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
2177                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
2178    
2179                          // backward search                          // backward search
2180                          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,
2181                                                  &frame->image, i, j,                                                  &frame->image, i, j,
2182                                                  frame->motion_flags,                                                  frame->motion_flags,
2183                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
2184                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
2185                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
2186    
2187                          // 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
2188    /*
2189                          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,
2190                                                  b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                                                  b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2191                                                  &frame->image,                                                  &frame->image,
2192                                                  i, j,                                                  i, j,
2193                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
2194                                                  frame->motion_flags,                                                  frame->motion_flags,
2195                                                  frame->quant, pParam,                                                  pParam,
2196                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
2197                                                  pMB, &best_sad);                                                  pMB, &best_sad,
2198                                                    &Data);
2199    */
2200                          switch (pMB->mode) {                          switch (pMB->mode) {
2201                                  case MODE_FORWARD:                                  case MODE_FORWARD:
2202                                          f_count++;                                          f_count++;
2203                                          f_predMV = pMB->mvs[0];                                          if (pParam->m_quarterpel) f_predMV = pMB->qmvs[0];
2204                                            else f_predMV = pMB->mvs[0];
2205                                          break;                                          break;
2206                                  case MODE_BACKWARD:                                  case MODE_BACKWARD:
2207                                          b_count++;                                          b_count++;
2208                                          b_predMV = pMB->b_mvs[0];                                          if (pParam->m_quarterpel) b_predMV = pMB->b_qmvs[0];
2209                                            else b_predMV = pMB->b_mvs[0];
2210                                          break;                                          break;
2211                                  case MODE_INTERPOLATE:                                  case MODE_INTERPOLATE:
2212                                          i_count++;                                          i_count++;
2213                                            if (pParam->m_quarterpel) {
2214                                                    f_predMV = pMB->qmvs[0];
2215                                                    b_predMV = pMB->b_qmvs[0];
2216                                            } else {
2217                                          f_predMV = pMB->mvs[0];                                          f_predMV = pMB->mvs[0];
2218                                          b_predMV = pMB->b_mvs[0];                                          b_predMV = pMB->b_mvs[0];
2219                                            }
2220                                          break;                                          break;
2221                                  case MODE_DIRECT:                                  case MODE_DIRECT:
2222                                  case MODE_DIRECT_NO4V:                                  case MODE_DIRECT_NO4V:
# Line 1381  Line 2227 
2227                          }                          }
2228                  }                  }
2229          }          }
2230            free(qimage);
 //      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);  
   
2231  }  }
2232    
2233  /* Hinted ME starts here */  /* Hinted ME starts here */
2234    
 static __inline void  
 Search8hinted(  const SearchData * const OldData,  
                                 const int x, const int y,  
                                 const uint32_t MotionFlags,  
                                 const MBParam * const pParam,  
                                 MACROBLOCK * const pMB,  
                                 const MACROBLOCK * const pMBs,  
                                 const int block)  
 {  
         SearchData Data;  
         MainSearchFunc *MainSearchPtr;  
   
         Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);  
         Data.iMinSAD = OldData->iMinSAD + 1 + block;  
         Data.currentMV = OldData->currentMV+1+block;  
         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));  
   
         CheckCandidate = CheckCandidate8;  
   
         if (block != 0)  
                 *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *  
                                                                 d_mv_bits(      Data.currentMV->x - Data.predMV.x,  
                                                                                         Data.currentMV->y - Data.predMV.y,  
                                                                                         Data.iFcode);  
   
   
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,  
                                 pParam->width, pParam->height, OldData->iFcode);  
   
         if (pMB->mode == MODE_INTER4V) {  
                 int dummy;  
                 CheckCandidate8(pMB->mvs[block].x, pMB->mvs[block].y, 0, &dummy, &Data); }  
   
         if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;  
                 else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;  
                         else MainSearchPtr = DiamondSearch;  
   
         (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);  
   
         if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);  
   
         pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;  
         pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;  
         pMB->mvs[block] = *(Data.currentMV);  
         pMB->sad8[block] =  4 * (*(Data.iMinSAD));  
 }  
   
   
2235  static void  static void
2236  SearchPhinted ( const uint8_t * const pRef,  SearchPhinted ( const IMAGE * const pRef,
2237                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
2238                                  const uint8_t * const pRefV,                                  const uint8_t * const pRefV,
2239                                  const uint8_t * const pRefHV,                                  const uint8_t * const pRefHV,
# Line 1455  Line 2242 
2242                                  const int y,                                  const int y,
2243                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
2244                                  const uint32_t iQuant,                                  const uint32_t iQuant,
                                 const uint32_t iFcode,  
2245                                  const MBParam * const pParam,                                  const MBParam * const pParam,
2246                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
2247                                  int inter4v,                                  int inter4v,
2248                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
2249                                    SearchData * const Data)
2250  {  {
2251    
2252          const int32_t iEdgedWidth = pParam->edged_width;          int i, t;
   
         int i;  
         VECTOR currentMV[5];  
         int32_t iMinSAD[5];  
         int32_t temp[5];  
2253          MainSearchFunc * MainSearchPtr;          MainSearchFunc * MainSearchPtr;
         SearchData Data;  
   
         Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);  
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,  
                                 pParam->width, pParam->height, iFcode);  
2254    
2255          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
2256          Data.iEdgedWidth = iEdgedWidth;          Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
2257          Data.currentMV = currentMV;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2258          Data.iMinSAD = iMinSAD;                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
2259          Data.Ref = pRef + (x + iEdgedWidth*y)*16;  
2260          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
2261          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8;
2262          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;          Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8;
2263          Data.temp = temp;  
2264          Data.iQuant = iQuant;          Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16;
2265          Data.iFcode = iFcode;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
2266            Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
2267            Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
2268            Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
2269            Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
2270    
2271          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
2272                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
2273                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
2274                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
2275                  Data.max_dy = EVEN(Data.max_dy);                  Data->max_dy = EVEN(Data->max_dy);
2276          }          }
2277    
2278          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;          for(i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
2279    
2280          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
2281    
2282          if (inter4v)          if (inter4v || pParam->m_quarterpel || Data->chroma) CheckCandidate = CheckCandidate16;
                 CheckCandidate = CheckCandidate16;  
2283          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
2284    
   
2285          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);
2286          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);
2287          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->max_dx) pMB->mvs[0].x = Data->max_dx; // this is in case iFcode changed
2288          if (pMB->mvs[0].x < Data.min_dx) pMB->mvs[0].x = Data.min_dx;          if (pMB->mvs[0].x < Data->min_dx) pMB->mvs[0].x = Data->min_dx;
2289          if (pMB->mvs[0].y > Data.max_dy) pMB->mvs[0].y = Data.max_dy;          if (pMB->mvs[0].y > Data->max_dy) pMB->mvs[0].y = Data->max_dy;
2290          if (pMB->mvs[0].y < Data.min_dy) pMB->mvs[0].y = Data.min_dy;          if (pMB->mvs[0].y < Data->min_dy) pMB->mvs[0].y = Data->min_dy;
2291    
2292          CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);          (*CheckCandidate)(pMB->mvs[0].x, pMB->mvs[0].y, 0, &t, Data);
2293    
2294          if (pMB->mode == MODE_INTER4V)          if (pMB->mode == MODE_INTER4V)
2295                  for (i = 1; i < 4; i++) { // all four vectors will be used as four predictions for 16x16 search                  for (i = 1; i < 4; i++) { // all four vectors will be used as four predictions for 16x16 search
2296                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);
2297                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);
2298                          if (!(make_mask(pMB->mvs, i)))                          if (!(make_mask(pMB->mvs, i)))
2299                                  CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);                                  (*CheckCandidate)(pMB->mvs[i].x, pMB->mvs[i].y, 0, &t, Data);
2300                  }                  }
2301    
2302          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1526  Line 2305 
2305                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
2306                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
2307    
2308          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
2309    
2310          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
2311    
2312          if (inter4v)          for(i = 0; i < 5; i++) {
2313                  for(i = 0; i < 4; i++)                  Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
2314                          Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                  Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
2315            }
2316    
2317            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
2318                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2319                                    pParam->width, pParam->height, Data->iFcode, 0);
2320                    CheckCandidate = CheckCandidate16_qpel;
2321                    QuarterpelRefine(Data);
2322            }
2323    
2324            if (inter4v) {
2325                    SearchData Data8;
2326                    Data8.iFcode = Data->iFcode;
2327                    Data8.lambda8 = Data->lambda8;
2328                    Data8.iEdgedWidth = Data->iEdgedWidth;
2329                    Data8.RefQ = Data->RefQ;
2330                    Data8.qpel = Data->qpel;
2331                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
2332                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
2333                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
2334                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
2335    
2336                    if (Data->chroma) {
2337                            int sum, dx, dy;
2338    
2339                            if(pParam->m_quarterpel)
2340                                    sum = (pMB->qmvs[0].y/2 + pMB->qmvs[1].y/2 + pMB->qmvs[2].y/2 + pMB->qmvs[3].y/2);
2341                            else sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
2342                            dy = (sum ? SIGN(sum) *
2343                                      (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2) : 0);
2344    
2345                            if(pParam->m_quarterpel)
2346                                    sum = (pMB->qmvs[0].x/2 + pMB->qmvs[1].x/2 + pMB->qmvs[2].x/2 + pMB->qmvs[3].x/2);
2347                            else sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
2348                            dx = (sum ? SIGN(sum) *
2349                                      (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2) : 0);
2350                            Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);
2351                    }
2352            }
2353    
2354          if (!(inter4v) ||          if (!(inter4v) ||
2355                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3] +
2356                                                            Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
2357  // INTER MODE  // INTER MODE
   
2358                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
2359                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
2360                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
2361    
2362                    pMB->qmvs[0] = pMB->qmvs[1]
2363                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
2364    
2365                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
2366                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
2367    
2368                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
2369                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predQMV.x;
2370                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predQMV.y;
2371          } else {          } else {
2372  // INTER4V MODE; all other things are already set in Search8hinted                          pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
2373                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
2374                    }
2375            } else {
2376    // INTER4V MODE; all other things are already set in Search8
2377                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
2378                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3]
2379                                                    + Data->iMinSAD[4] + IMV16X16 * iQuant;
2380          }          }
2381    
2382  }  }
# Line 1568  Line 2394 
2394          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
2395    
2396          uint32_t x, y;          uint32_t x, y;
2397            uint8_t * qimage;
2398            int32_t temp[5], quant = current->quant;
2399            int32_t iMinSAD[5];
2400            VECTOR currentMV[5], currentQMV[5];
2401            SearchData Data;
2402            Data.iEdgedWidth = pParam->edged_width;
2403            Data.currentMV = currentMV;
2404            Data.currentQMV = currentQMV;
2405            Data.iMinSAD = iMinSAD;
2406            Data.temp = temp;
2407            Data.iFcode = current->fcode;
2408            Data.rounding = pParam->m_rounding_type;
2409            Data.qpel = pParam->m_quarterpel;
2410            Data.chroma = current->global_flags & XVID_ME_COLOUR;
2411    
2412            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
2413                    return; // allocate some mem for qpel interpolated blocks
2414                                      // somehow this is dirty since I think we shouldn't use malloc outside
2415                                      // encoder_create() - so please fix me!
2416    
2417            Data.RefQ = qimage;
2418    
2419          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
2420    
2421          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
2422                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
                         int32_t sad00;  
2423    
2424                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2425    
# Line 1583  Line 2429 
2429                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
2430                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
2431                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant; }
2432                            else {
2433                                    if (pMB->dquant != NO_CHANGE) {
2434                                            quant += DQtab[pMB->dquant];
2435                                            if (quant > 31) quant = 31;
2436                                            else if (quant < 1) quant = 1;
2437                                    }
2438                                    pMB->quant = quant;
2439                            }
2440    
2441                          if (pMB->dquant == NO_CHANGE) //no skip otherwise, anyway                          SearchPhinted(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
2442                                  sad00 = pMB->sad16                                                          y, current->motion_flags, pMB->quant,
2443                                          = sad16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
2444                                                                  pRef->y + (x + y * pParam->edged_width) * 16,                                                          &Data);
                                                                 pParam->edged_width, 256*4096 );  
                         else sad00 = 256*4096;  
2445    
2446                    }
2447            }
2448            free(qimage);
2449    }
2450    
2451  //initial skip decision  static __inline int
2452    MEanalyzeMB (   const uint8_t * const pRef,
2453                                    const uint8_t * const pCur,
2454                                    const int x,
2455                                    const int y,
2456                                    const MBParam * const pParam,
2457                                    const MACROBLOCK * const pMBs,
2458                                    MACROBLOCK * const pMB,
2459                                    SearchData * const Data)
2460    {
2461    
2462                          if ( (pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)          int i = 255, mask;
2463                                  && ( //(pMB->mode == MODE_NOT_CODED) ||          VECTOR pmv[3];
2464                                          (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant) )) ) {          *(Data->iMinSAD) = MV_MAX_ERROR;
2465                                  if (sad00 < pMB->quant * INITIAL_SKIP_THRESH) {  
2466                                          SkipMacroblockP(pMB, sad00);          //median is only used as prediction. it doesn't have to be real
2467                                          continue; } //skipped          if (x == 1 && y == 1) Data->predMV.x = Data->predMV.y = 0;
2468            else
2469                    if (x == 1) //left macroblock does not have any vector now
2470                            Data->predMV = (pMB - pParam->mb_width)->mvs[0]; // top instead of median
2471                    else if (y == 1) // top macroblock don't have it's vector
2472                            Data->predMV = (pMB - 1)->mvs[0]; // left instead of median
2473                            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); //else median
2474    
2475            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2476                                    pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
2477    
2478            Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
2479            Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
2480    
2481            pmv[1].x = EVEN(pMB->mvs[0].x);
2482            pmv[1].y = EVEN(pMB->mvs[0].y);
2483            pmv[2].x = EVEN(Data->predMV.x);
2484            pmv[2].y = EVEN(Data->predMV.y);
2485            pmv[0].x = pmv[0].y = 0;
2486    
2487            (*CheckCandidate)(0, 0, 255, &i, Data);
2488    
2489    //early skip for 0,0
2490            if (*Data->iMinSAD < MAX_SAD00_FOR_SKIP * 4) {
2491                    pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
2492                    pMB->mode = MODE_NOT_CODED;
2493                    return 0;
2494                          }                          }
                         else sad00 = 256*4096;  
2495    
2496                          if (pMB->mode == MODE_NOT_CODED)          if (!(mask = make_mask(pmv, 1)))
2497                                  SearchP(        pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                  (*CheckCandidate)(pmv[1].x, pmv[1].y, mask, &i, Data);
2498                                                          y, current->motion_flags, pMB->quant,          if (!(mask = make_mask(pmv, 2)))
2499                                                          current->fcode, pParam, pMBs, reference->mbs,                  (*CheckCandidate)(pmv[2].x, pmv[2].y, mask, &i, Data);
2500                                                          current->global_flags & XVID_INTER4V, pMB);  
2501            if (*Data->iMinSAD > MAX_SAD00_FOR_SKIP * 4) // diamond only if needed
2502                    DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
2503    
2504            pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
2505            pMB->mode = MODE_INTER;
2506            return *(Data->iMinSAD);
2507    }
2508    
2509    #define INTRA_THRESH    1350
2510    #define INTER_THRESH    900
2511    
2512    
2513    int
2514    MEanalysis(     const IMAGE * const pRef,
2515                            FRAMEINFO * const Current,
2516                            MBParam * const pParam,
2517                            int maxIntra, //maximum number if non-I frames
2518                            int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame
2519                            int bCount) // number if B frames in a row
2520    {
2521            uint32_t x, y, intra = 0;
2522            int sSAD = 0;
2523            MACROBLOCK * const pMBs = Current->mbs;
2524            const IMAGE * const pCurrent = &Current->image;
2525            int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH;
2526    
2527            VECTOR currentMV;
2528            int32_t iMinSAD;
2529            SearchData Data;
2530            Data.iEdgedWidth = pParam->edged_width;
2531            Data.currentMV = &currentMV;
2532            Data.iMinSAD = &iMinSAD;
2533            Data.iFcode = Current->fcode;
2534            CheckCandidate = CheckCandidate16no4vI;
2535    
2536            if (intraCount < 10) // we're right after an I frame
2537                    IntraThresh += 4 * (intraCount - 10) * (intraCount - 10);
2538                          else                          else
2539                                  SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                  if ( 5*(maxIntra - intraCount) < maxIntra) // we're close to maximum. 2 sec when max is 10 sec
2540                                                          y, current->motion_flags, pMB->quant,                          IntraThresh -= (IntraThresh * (maxIntra - 5*(maxIntra - intraCount)))/maxIntra;
                                                         current->fcode, pParam, pMBs,  
                                                         current->global_flags & XVID_INTER4V, pMB);  
2541    
 /* final skip decision, a.k.a. "the vector you found, really that good?" */  
                         if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)  
                                 if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)  
                                 SkipMacroblockP(pMB, sad00);  
2542    
2543            InterThresh += 300 * (1 - bCount);
2544            if (InterThresh < 200) InterThresh = 200;
2545    
2546            if (sadInit) (*sadInit) ();
2547    
2548            for (y = 1; y < pParam->mb_height-1; y++) {
2549                    for (x = 1; x < pParam->mb_width-1; x++) {
2550                            int sad, dev;
2551                            MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2552    
2553                            sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
2554                                                                    pParam, pMBs, pMB, &Data);
2555    
2556                            if (sad > IntraThresh) {
2557                                    dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
2558                                                              pParam->edged_width);
2559                                    if (dev + IntraThresh < sad) {
2560                                            pMB->mode = MODE_INTRA;
2561                                            if (++intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame
2562                                    }
2563                            }
2564                            sSAD += sad;
2565                    }
2566            }
2567            sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2568            if (sSAD > InterThresh ) return 1; //P frame
2569            emms();
2570            return 0; // B frame
2571    
2572    }
2573    
2574    int
2575    FindFcode(      const MBParam * const pParam,
2576                            const FRAMEINFO * const current)
2577    {
2578            uint32_t x, y;
2579            int max = 0, min = 0, i;
2580    
2581            for (y = 0; y < pParam->mb_height; y++) {
2582                    for (x = 0; x < pParam->mb_width; x++) {
2583    
2584                            MACROBLOCK *pMB = &current->mbs[x + y * pParam->mb_width];
2585                            for(i = 0; i < (pMB->mode == MODE_INTER4V ? 4:1); i++) {
2586                                    if (pMB->mvs[i].x > max) max = pMB->mvs[i].x;
2587                                    if (pMB->mvs[i].y > max) max = pMB->mvs[i].y;
2588    
2589                                    if (pMB->mvs[i].x < min) min = pMB->mvs[i].x;
2590                                    if (pMB->mvs[i].y < min) min = pMB->mvs[i].y;
2591                  }                  }
2592          }          }
2593  }  }
2594    
2595            min = -min;
2596            max += 1;
2597            if (min > max) max = min;
2598            if (pParam->m_quarterpel) max *= 2;
2599    
2600            for (i = 1; (max > 32 << (i - 1)); i++);
2601            return i;
2602    }
2603    
2604    static void
2605    CheckGMC(int x, int y, const int dir, int * iDirection,
2606                    const MACROBLOCK * const pMBs, uint32_t * bestcount, VECTOR * GMC,
2607                    const MBParam * const pParam)
2608    {
2609            uint32_t mx, my, a, count = 0;
2610    
2611            for (my = 1; my < pParam->mb_height-1; my++)
2612                    for (mx = 1; mx < pParam->mb_width-1; mx++) {
2613                            VECTOR mv;
2614                            const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2615                            if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED) continue;
2616                            mv = pMB->mvs[0];
2617                            a = ABS(mv.x - x) + ABS(mv.y - y);
2618                            if (a < 6) count += 6 - a;
2619                    }
2620    
2621            if (count > *bestcount) {
2622                    *bestcount = count;
2623                    *iDirection = dir;
2624                    GMC->x = x; GMC->y = y;
2625            }
2626    }
2627    
2628    
2629    static VECTOR
2630    GlobalMotionEst(const MACROBLOCK * const pMBs, const MBParam * const pParam, const uint32_t iFcode)
2631    {
2632    
2633            uint32_t count, bestcount = 0;
2634            int x, y;
2635            VECTOR gmc = {0,0};
2636            int step, min_x, max_x, min_y, max_y;
2637            uint32_t mx, my;
2638            int iDirection, bDirection;
2639    
2640            min_x = min_y = -32<<iFcode;
2641            max_x = max_y = 32<<iFcode;
2642    
2643    //step1: let's find a rough camera panning
2644            for (step = 32; step >= 2; step /= 2) {
2645                    bestcount = 0;
2646                    for (y = min_y; y <= max_y; y += step)
2647                            for (x = min_x ; x <= max_x; x += step) {
2648                                    count = 0;
2649                                    //for all macroblocks
2650                                    for (my = 1; my < pParam->mb_height-1; my++)
2651                                            for (mx = 1; mx < pParam->mb_width-1; mx++) {
2652                                                    const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2653                                                    VECTOR mv;
2654    
2655                                                    if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
2656                                                            continue;
2657    
2658                                                    mv = pMB->mvs[0];
2659                                                    if ( ABS(mv.x - x) <= step && ABS(mv.y - y) <= step )   /* GMC translation is always halfpel-res */
2660                                                            count++;
2661                                            }
2662                                    if (count >= bestcount) { bestcount = count; gmc.x = x; gmc.y = y; }
2663                            }
2664                    min_x = gmc.x - step;
2665                    max_x = gmc.x + step;
2666                    min_y = gmc.y - step;
2667                    max_y = gmc.y + step;
2668    
2669            }
2670    
2671            if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10)
2672                    gmc.x = gmc.y = 0; //no camara pan, no GMC
2673    
2674    // step2: let's refine camera panning using gradiend-descent approach.
2675    // TODO: more warping points may be evaluated here (like in interpolate mode search - two vectors in one diamond)
2676            bestcount = 0;
2677            CheckGMC(gmc.x, gmc.y, 255, &iDirection, pMBs, &bestcount, &gmc, pParam);
2678            do {
2679                    x = gmc.x; y = gmc.y;
2680                    bDirection = iDirection; iDirection = 0;
2681                    if (bDirection & 1) CheckGMC(x - 1, y, 1+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2682                    if (bDirection & 2) CheckGMC(x + 1, y, 2+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2683                    if (bDirection & 4) CheckGMC(x, y - 1, 1+2+4, &iDirection, pMBs, &bestcount, &gmc, pParam);
2684                    if (bDirection & 8) CheckGMC(x, y + 1, 1+2+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2685    
2686            } while (iDirection);
2687    
2688            if (pParam->m_quarterpel) {
2689                    gmc.x *= 2;
2690                    gmc.y *= 2;     /* we store the halfpel value as pseudo-qpel to make comparison easier */
2691            }
2692    
2693            return gmc;
2694    }

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

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