[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 644, Tue Nov 12 14:46:03 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    
65  //FILE * debug;  #define iDiamondSize 2
66    
67  static __inline int  static __inline int
68  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 89 
89          return xb + yb;          return xb + yb;
90  }  }
91    
92  /* CHACK_CANDIATE FUNCTIONS START */  static int32_t
93    ChromaSAD(int dx, int dy, const SearchData * const data)
94    {
95            int sad;
96            dx = (dx >> 1) + roundtab_79[dx & 0x3];
97            dy = (dy >> 1) + roundtab_79[dy & 0x3];
98    
99            switch (((dx & 1) << 1) + (dy & 1))     { // ((dx%2)?2:0)+((dy%2)?1:0)
100                    case 0:
101                            sad = sad8(data->CurU, data->RefCU + (dy/2) * (data->iEdgedWidth/2) + dx/2, data->iEdgedWidth/2);
102                            sad += sad8(data->CurV, data->RefCV + (dy/2) * (data->iEdgedWidth/2) + dx/2, data->iEdgedWidth/2);
103                            break;
104                    case 1:
105                            dx = dx / 2; dy = (dy - 1) / 2;
106                            sad = sad8bi(data->CurU, data->RefCU + dy * (data->iEdgedWidth/2) + dx, data->RefCU + (dy+1) * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2);
107                            sad += sad8bi(data->CurV, data->RefCV + dy * (data->iEdgedWidth/2) + dx, data->RefCV + (dy+1) * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2);
108                            break;
109                    case 2:
110                            dx = (dx - 1) / 2; dy = dy / 2;
111                            sad = sad8bi(data->CurU, data->RefCU + dy * (data->iEdgedWidth/2) + dx, data->RefCU + dy * (data->iEdgedWidth/2) + dx+1, data->iEdgedWidth/2);
112                            sad += sad8bi(data->CurV, data->RefCV + dy * (data->iEdgedWidth/2) + dx, data->RefCV + dy * (data->iEdgedWidth/2) + dx+1, data->iEdgedWidth/2);
113                            break;
114                    default:
115                            dx = (dx - 1) / 2; dy = (dy - 1) / 2;
116                            interpolate8x8_halfpel_hv(data->RefQ,
117                                                                             data->RefCU + dy * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2,
118                                                                             data->rounding);
119                            sad = sad8(data->CurU, data->RefQ, data->iEdgedWidth/2);
120                            interpolate8x8_halfpel_hv(data->RefQ,
121                                                                             data->RefCV + dy * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2,
122                                                                             data->rounding);
123                            sad += sad8(data->CurV, data->RefQ, data->iEdgedWidth/2);
124                            break;
125            }
126            return sad;
127    }
128    
129    
130    /* CHECK_CANDIATE FUNCTIONS START */
131    
132    
133  static void  static void
134  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)
135  {  {
         int32_t * const sad = data->temp;  
 //      static int32_t sad[5];  
136          int t;          int t;
137          const uint8_t * Reference;          const uint8_t * Reference;
138    
# Line 99  Line 146 
146                  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;
147          }          }
148    
149          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, sad+1);          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
150    
151            if (data->qpel) t = d_mv_bits(2*x - data->predQMV.x, 2*y - data->predQMV.y, data->iFcode);
152            else t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
153    
154          t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          data->temp[0] += (data->lambda16 * t * data->temp[0])/1000;
155          data->temp[0] += lambda_vec16[data->iQuant] * t;          data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))/100;
156          data->temp[1] += lambda_vec8[data->iQuant] * t;  
157            if (data->chroma) data->temp[0] += ChromaSAD(x, y, data);
158    
159          if (data->temp[0] < data->iMinSAD[0]) {          if (data->temp[0] < data->iMinSAD[0]) {
160                  data->iMinSAD[0] = data->temp[0];                  data->iMinSAD[0] = data->temp[0];
# Line 138  Line 189 
189                  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;
190          }          }
191    
192          sad = lambda_vec16[data->iQuant] *          sad = sad16(data->Cur, Reference, data->iEdgedWidth, MV_MAX_ERROR);
193                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          sad += (data->lambda16 * d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode) * sad)/1000;
         sad += sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);  
194    
195          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
196                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 149  Line 199 
199  }  }
200    
201  static void  static void
202    CheckCandidate16_qpel(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
203    
204    // CheckCandidate16 variant which expects x and y in quarter pixel resolution
205    // Important: This is no general usable routine! x and y must be +/-1 (qpel resolution!)
206    // around currentMV!
207    {
208            int t;
209            uint8_t * Reference = (uint8_t *)data->RefQ;
210            const uint8_t *ref1, *ref2, *ref3, *ref4;
211            VECTOR halfpelMV = *(data->currentMV);
212    
213            int32_t iEdgedWidth = data->iEdgedWidth;
214            uint32_t rounding = data->rounding;
215    
216            if (( x > data->max_dx) || ( x < data->min_dx)
217                    || ( y > data->max_dy) || (y < data->min_dy)) return;
218    
219            GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1); // this refenrence is used in all cases
220            switch( ((x&1)<<1) + (y&1) )
221            {
222            case 0: // pure halfpel position - shouldn't happen during a refinement step
223                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, Reference);
224                    break;
225    
226            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
227                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
228                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
229                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding);
230                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding);
231                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding);
232                    break;
233    
234            case 2: // x qpel, y halfpel - left or right during qpel refinement
235                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref2);
236                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
237                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding);
238                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding);
239                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding);
240                    break;
241    
242            default: // x and y in qpel resolution - the "corners" (top left/right and
243                             // bottom left/right) during qpel refinement
244                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
245                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref3);
246                    GET_REFERENCE(x - halfpelMV.x, y - halfpelMV.y, ref4);
247    
248                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
249                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
250                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
251                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
252                    break;
253            }
254    
255            data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp+1);
256    
257            t = d_mv_bits(x - data->predQMV.x, y - data->predQMV.y, data->iFcode);
258            data->temp[0] += (data->lambda16 * t * data->temp[0])/1000;
259            data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))/100;
260    
261            if (data->chroma)
262                    data->temp[0] += ChromaSAD(x/2, y/2, data);
263    
264            if (data->temp[0] < data->iMinSAD[0]) {
265                    data->iMinSAD[0] = data->temp[0];
266                    data->currentQMV[0].x = x; data->currentQMV[0].y = y;
267            /*      *dir = Direction;*/ }
268    
269            if (data->temp[1] < data->iMinSAD[1]) {
270                    data->iMinSAD[1] = data->temp[1]; data->currentQMV[1].x = x; data->currentQMV[1].y = y; }
271            if (data->temp[2] < data->iMinSAD[2]) {
272                    data->iMinSAD[2] = data->temp[2]; data->currentQMV[2].x = x; data->currentQMV[2].y = y; }
273            if (data->temp[3] < data->iMinSAD[3]) {
274                    data->iMinSAD[3] = data->temp[3]; data->currentQMV[3].x = x; data->currentQMV[3].y = y; }
275            if (data->temp[4] < data->iMinSAD[4]) {
276                    data->iMinSAD[4] = data->temp[4]; data->currentQMV[4].x = x; data->currentQMV[4].y = y; }
277    }
278    
279    static void
280    CheckCandidate16no4vI(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
281    {
282            int32_t sad;
283    
284            if (( x > data->max_dx) || ( x < data->min_dx)
285                    || ( y > data->max_dy) || (y < data->min_dy)) return;
286    
287            sad = sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),
288                                            data->iEdgedWidth, 256*4096);
289    
290            if (sad < *(data->iMinSAD)) {
291                    *(data->iMinSAD) = sad;
292                    data->currentMV[0].x = x; data->currentMV[0].y = y;
293                    *dir = Direction; }
294    }
295    
296    
297    static void
298  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)
299  {  {
300          int32_t sad;          int32_t sad;
# Line 173  Line 319 
319                  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;
320          }          }
321    
322          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) );  
323    
324          sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);          sad += (data->lambda16 *
325                            ( d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode) +
326                              d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode)) * sad)/1000;
327    
328          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
329                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 188  Line 334 
334  static void  static void
335  CheckCandidateDirect(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidateDirect(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
336  {  {
337          int32_t sad;          int32_t sad = 0;
338          int k;          int k;
339          const uint8_t *ReferenceF;          const uint8_t *ReferenceF;
340          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
# Line 196  Line 342 
342    
343          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
344    
         sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);  
   
345          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
346                  mvs.x = data->directmvF[k].x + x;                  mvs.x = data->directmvF[k].x + x;
347                  b_mvs.x = ((x == 0) ?                  b_mvs.x = ((x == 0) ?
# Line 235  Line 379 
379                  if (sad > *(data->iMinSAD)) return;                  if (sad > *(data->iMinSAD)) return;
380          }          }
381    
382            sad += (data->lambda16 * d_mv_bits(x, y, 1) * sad)/1000;
383    
384          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
385                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
386                  data->currentMV->x = x; data->currentMV->y = y;                  data->currentMV->x = x; data->currentMV->y = y;
# Line 249  Line 395 
395          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
396          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
397    
398          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);  
399    
400          mvs.x = data->directmvF[0].x + x;          mvs.x = data->directmvF[0].x + x;
401          b_mvs.x = ((x == 0) ?          b_mvs.x = ((x == 0) ?
# Line 282  Line 426 
426                  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;
427          }          }
428    
429          sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
430            sad += (data->lambda16 * d_mv_bits(x, y, 1) * sad)/1000;
431    
432          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
433                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 293  Line 438 
438  static void  static void
439  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)
440  {  {
441          int32_t sad;          int32_t sad; int t;
442          const uint8_t * Reference;          const uint8_t * Reference;
443    
444          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
# Line 308  Line 453 
453          }          }
454    
455          sad = sad8(data->Cur, Reference, data->iEdgedWidth);          sad = sad8(data->Cur, Reference, data->iEdgedWidth);
456          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);
457            else t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
458    
459            sad += (data->lambda8 * t * (sad+NEIGH_8X8_BIAS))/100;
460    
461          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
462                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 316  Line 464 
464                  *dir = Direction; }                  *dir = Direction; }
465  }  }
466    
467  /* CHACK_CANDIATE FUNCTIONS END */  static void
468    CheckCandidate8_qpel(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
469    // CheckCandidate16no4v variant which expects x and y in quarter pixel resolution
470    // Important: This is no general usable routine! x and y must be +/-1 (qpel resolution!)
471    // around currentMV!
472    
473    {
474            int32_t sad;
475            uint8_t *Reference = (uint8_t *) data->RefQ;
476            const uint8_t *ref1, *ref2, *ref3, *ref4;
477            VECTOR halfpelMV = *(data->currentMV);
478    
479            int32_t iEdgedWidth = data->iEdgedWidth;
480            uint32_t rounding = data->rounding;
481    
482            if (( x > data->max_dx) || ( x < data->min_dx)
483                    || ( y > data->max_dy) || (y < data->min_dy)) return;
484    
485            GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
486            switch( ((x&1)<<1) + (y&1) )
487            {
488            case 0: // pure halfpel position - shouldn't happen during a refinement step
489                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, Reference);
490                    break;
491    
492            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
493                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
494    
495                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
496                    break;
497    
498            case 2: // x qpel, y halfpel - left or right during qpel refinement
499                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref2);
500    
501                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
502                    break;
503    
504            default: // x and y in qpel resolution - the "corners" (top left/right and
505                             // bottom left/right) during qpel refinement
506                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
507                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref3);
508                    GET_REFERENCE(x - halfpelMV.x, y - halfpelMV.y, ref4);
509    
510                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
511                    break;
512            }
513    
514            sad = sad8(data->Cur, Reference, data->iEdgedWidth);
515            sad += (data->lambda8 * d_mv_bits(x - data->predQMV.x, y - data->predQMV.y, data->iFcode) * (sad+NEIGH_8X8_BIAS))/100;
516    
517            if (sad < *(data->iMinSAD)) {
518                    *(data->iMinSAD) = sad;
519                    data->currentQMV->x = x; data->currentQMV->y = y;
520                    *dir = Direction; }
521    }
522    
523    /* CHECK_CANDIATE FUNCTIONS END */
524    
525  /* MAINSEARCH FUNCTIONS START */  /* MAINSEARCH FUNCTIONS START */
526    
# Line 484  Line 688 
688          CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);          CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);
689  }  }
690    
691    
692    static void
693    QuarterpelRefine(const SearchData * const data)
694    {
695    /* Perform quarter pixel refinement*/
696    
697            VECTOR backupMV = *(data->currentQMV);
698            int iDirection; //not needed
699    
700            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);
701            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);
702            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);
703            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y + 1, 0);
704    
705            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y, 0);
706            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y, 0);
707    
708            CHECK_CANDIDATE(backupMV.x, backupMV.y + 1, 0);
709            CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);
710    
711    }
712    
713  static __inline int  static __inline int
714  SkipDecisionP(const IMAGE * current, const IMAGE * reference,  SkipDecisionP(const IMAGE * current, const IMAGE * reference,
715                                                          const int x, const int y,                                                          const int x, const int y,
# Line 497  Line 723 
723          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,
724                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);
725          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
726          sadC += sad8(current->v + x*8 + y*(iEdgedWidth/2)*8,          sadC += sad8(current->v + (x + y*(iEdgedWidth/2))*8,
727                                          reference->v + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                          reference->v + (x + y*(iEdgedWidth/2))*8, iEdgedWidth/2);
728          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
729    
730          return 1;          return 1;
# Line 508  Line 734 
734  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)
735  {  {
736          pMB->mode = MODE_NOT_CODED;          pMB->mode = MODE_NOT_CODED;
737          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;
738          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;
739    
740            pMB->qmvs[0].x = pMB->qmvs[1].x = pMB->qmvs[2].x = pMB->qmvs[3].x = 0;
741            pMB->qmvs[0].y = pMB->qmvs[1].y = pMB->qmvs[2].y = pMB->qmvs[3].y = 0;
742    
743          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;
744  }  }
745    
# Line 530  Line 760 
760    
761          uint32_t x, y;          uint32_t x, y;
762          uint32_t iIntra = 0;          uint32_t iIntra = 0;
763          int32_t InterBias;          int32_t InterBias, quant = current->quant, sad00;
764            uint8_t *qimage;
765    
766            // some pre-initialized thingies for SearchP
767            int32_t temp[5];
768            VECTOR currentMV[5];
769            VECTOR currentQMV[5];
770            int32_t iMinSAD[5];
771            SearchData Data;
772            Data.iEdgedWidth = pParam->edged_width;
773            Data.currentMV = currentMV;
774            Data.currentQMV = currentQMV;
775            Data.iMinSAD = iMinSAD;
776            Data.temp = temp;
777            Data.iFcode = current->fcode;
778            Data.rounding = pParam->m_rounding_type;
779            Data.qpel = pParam->m_quarterpel;
780            Data.chroma = current->global_flags & XVID_ME_COLOUR;
781    
782            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
783                    return 1; // allocate some mem for qpel interpolated blocks
784                                      // somehow this is dirty since I think we shouldn't use malloc outside
785                                      // encoder_create() - so please fix me!
786            Data.RefQ = qimage;
787          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
788    
789          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
790                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
   
791                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
792                          int32_t sad00 =  pMB->sad16  
793                            pMB->sad16
794                                  = sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,                                  = sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,
795                                                          pRef->y + (x + y * pParam->edged_width) * 16,                                                          pRef->y + (x + y * pParam->edged_width) * 16,
796                                                          pParam->edged_width, pMB->sad8 );                                                          pParam->edged_width, pMB->sad8 );
797    
798                            if (Data.chroma) {
799                                    pMB->sad16 += sad8(pCurrent->u + x*8 + y*(pParam->edged_width/2)*8,
800                                                                    pRef->u + x*8 + y*(pParam->edged_width/2)*8, pParam->edged_width/2);
801    
802                                    pMB->sad16 += sad8(pCurrent->v + (x + y*(pParam->edged_width/2))*8,
803                                                                    pRef->v + (x + y*(pParam->edged_width/2))*8, pParam->edged_width/2);
804                            }
805    
806                            sad00 = pMB->sad16; //if no gmc; else sad00 = (..)
807    
808                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
809                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
810                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant;
811                            } else {
812                                    if (pMB->dquant != NO_CHANGE) {
813                                            quant += DQtab[pMB->dquant];
814                                            if (quant > 31) quant = 31;
815                                            else if (quant < 1) quant = 1;
816                                    }
817                                    pMB->quant = quant;
818                            }
819    
820  //initial skip decision  //initial skip decision
821    /* no early skip for GMC (global vector = skip vector is unknown!)  */
822                          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 */
823                                  && (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) ) {                                  if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * INITIAL_SKIP_THRESH)
824                                  if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {                                          if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
825                                                  SkipMacroblockP(pMB, sad00);                                                  SkipMacroblockP(pMB, sad00);
826                                                  continue;                                                  continue;
827                                  }                                  }
828                          } else sad00 = 256*4096; // skip not allowed - for final skip decision                          }
829    
830                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchP(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
831                                                  y, current->motion_flags, pMB->quant,                                                  y, current->motion_flags, pMB->quant,
832                                                  current->fcode, pParam, pMBs, reference->mbs,                                                  &Data, pParam, pMBs, reference->mbs,
833                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
834    
835  /* 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?" */
836                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)                          if (current->coding_type == P_VOP)      {
837                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)                                  if ( (pMB->dquant == NO_CHANGE) && (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)
838                                  { SkipMacroblockP(pMB, sad00); continue; }                                  && ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH) )
839                                            if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
840                                                    SkipMacroblockP(pMB, sad00);
841                                                    continue;
842                                            }
843                            }
844    
845  /* finally, intra decision */  /* finally, intra decision */
846    
847                          InterBias = MV16_INTER_BIAS;                          InterBias = MV16_INTER_BIAS;
848                          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
849                          if (y != 0)                          if (y != 0)
850                                  if ((pMB - pParam->mb_width)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - pParam->mb_width)->mode == MODE_INTRA ) InterBias -= 80;
851                          if (x != 0)                          if (x != 0)
852                                  if ((pMB - 1)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - 1)->mode == MODE_INTRA ) InterBias -= 80;
853    
854                            if (Data.chroma) InterBias += 50; // to compensate bigger SAD
855    
856                          if (InterBias < pMB->sad16)  {                          if (InterBias < pMB->sad16)  {
857                                  const int32_t deviation =                                  const int32_t deviation =
# Line 582  Line 859 
859                                                    pParam->edged_width);                                                    pParam->edged_width);
860    
861                                  if (deviation < (pMB->sad16 - InterBias)) {                                  if (deviation < (pMB->sad16 - InterBias)) {
862                                          if (++iIntra >= iLimit) return 1;                                          if (++iIntra >= iLimit) { free(qimage); return 1; }
863                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
864                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
865                                                  pMB->mvs[3] = zeroMV;                                                  pMB->mvs[3] = zeroMV;
866                                            pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] =
867                                                            pMB->qmvs[3] = zeroMV;
868                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
869                                                  pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
870                                  }                                  }
871                          }                          }
872                  }                  }
873          }          }
874            free(qimage);
875    
876            if (current->coding_type == S_VOP)      /* first GMC step only for S(GMC)-VOPs */
877                    current->GMC_MV = GlobalMotionEst( pMBs, pParam, current->fcode );
878            else
879                    current->GMC_MV = zeroMV;
880    
881          return 0;          return 0;
882  }  }
883    
# Line 601  Line 887 
887  static __inline int  static __inline int
888  make_mask(const VECTOR * const pmv, const int i)  make_mask(const VECTOR * const pmv, const int i)
889  {  {
890          int mask = 0xFF, j;          int mask = 255, j;
891          for (j = 0; j < i; j++) {          for (j = 0; j < i; j++) {
892                  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
893                  if (pmv[i].x == pmv[j].x) {                  if (pmv[i].x == pmv[j].x) {
# Line 625  Line 911 
911    
912          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour
913                  pmv[5].x = EVEN(pmv[3].x);                  pmv[5].x = EVEN(pmv[3].x);
914                  pmv[5].y = EVEN(pmv[3].y); }                  pmv[5].y = EVEN(pmv[3].y);
915          else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
916    
917          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
918          else pmv[3].x = pmv[3].y = 0;          else pmv[3].x = pmv[3].y = 0;
# Line 644  Line 930 
930    
931          if ((x != iWcount-1) && (y != iHcount-1)) {          if ((x != iWcount-1) && (y != iHcount-1)) {
932                  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
933                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y); }                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
934          else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
935  }  }
936    
937  static void  static void
938  SearchP(const uint8_t * const pRef,  SearchP(const IMAGE * const pRef,
939                  const uint8_t * const pRefH,                  const uint8_t * const pRefH,
940                  const uint8_t * const pRefV,                  const uint8_t * const pRefV,
941                  const uint8_t * const pRefHV,                  const uint8_t * const pRefHV,
# Line 658  Line 944 
944                  const int y,                  const int y,
945                  const uint32_t MotionFlags,                  const uint32_t MotionFlags,
946                  const uint32_t iQuant,                  const uint32_t iQuant,
947                  const uint32_t iFcode,                  SearchData * const Data,
948                  const MBParam * const pParam,                  const MBParam * const pParam,
949                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
950                  const MACROBLOCK * const prevMBs,                  const MACROBLOCK * const prevMBs,
# Line 666  Line 952 
952                  MACROBLOCK * const pMB)                  MACROBLOCK * const pMB)
953  {  {
954    
         const int32_t iEdgedWidth = pParam->edged_width;  
   
955          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
956          int32_t temp[5];          VECTOR pmv[7];
         VECTOR currentMV[5], pmv[7];  
         int32_t psad[4], iMinSAD[5];  
         MainSearchFunc * MainSearchPtr;  
         SearchData Data;  
957    
958          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)()
959          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,
960                                  pParam->width, pParam->height, iFcode);                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
961    
962          Data.predMV = pmv[0];          Data->predMV = pmv[0];
963          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
964          Data.iEdgedWidth = iEdgedWidth;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
965          Data.currentMV = currentMV;          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8;
966          Data.iMinSAD = iMinSAD;          Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8;
967          Data.Ref = pRef + (x + iEdgedWidth*y)*16;  
968          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16;
969          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
970          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
971          Data.temp = temp;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
972            Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
973            Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
974    
975          Data.iQuant = iQuant;          Data->lambda16 = lambda_vec16[iQuant];
976          Data.iFcode = iFcode;          Data->lambda8 = lambda_vec8[iQuant];
977    
978          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
979                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
980                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
981                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
982                  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];  
983    
984          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
985    
986            for(i = 0;  i < 5; i++)
987                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
988    
989            if (pParam->m_quarterpel) {
990                    Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
991                    i = d_mv_bits(Data->predQMV.x, Data->predQMV.y, Data->iFcode);
992            } else i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);
993    
994            Data->iMinSAD[0] = pMB->sad16 + (Data->lambda16 * i * pMB->sad16)/1000;
995            Data->iMinSAD[1] = pMB->sad8[0] + (Data->lambda8 * i * (pMB->sad8[0]+NEIGH_8X8_BIAS))/100;
996            Data->iMinSAD[2] = pMB->sad8[1];
997            Data->iMinSAD[3] = pMB->sad8[2];
998            Data->iMinSAD[4] = pMB->sad8[3];
999    
1000          if ((x == 0) && (y == 0)) threshA = 512;          if ((x == 0) && (y == 0)) threshA = 512;
1001          else {          else {
1002                  threshA = psad[0] + 20;                  threshA = Data->temp[0]; // that's when we keep this SAD atm
1003                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
1004                  if (threshA > 1024) threshA = 1024; }                  if (threshA > 1024) threshA = 1024; }
1005    
1006          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,
1007                                          prevMBs + x + y * pParam->mb_width);                                          prevMBs + x + y * pParam->mb_width);
1008    
1009          if (inter4v) CheckCandidate = CheckCandidate16;          if (inter4v || pParam->m_quarterpel || Data->chroma) CheckCandidate = CheckCandidate16;
1010          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
1011    
1012  /* main loop. checking all predictions */  /* main loop. checking all predictions */
1013    
1014          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
1015                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1016                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  (*CheckCandidate)(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1017                  if (iMinSAD[0] < threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1018          }          }
1019    
1020          if ((iMinSAD[0] <= threshA) ||          if ((Data->iMinSAD[0] <= threshA) ||
1021                          (MVequal(currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
1022                          (iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {                          (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {
1023                  inter4v = 0;                  inter4v = 0;
1024                  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;  
                 }  
         }  
1025    
1026          if (MotionFlags & PMV_USESQUARES16)                  MainSearchFunc * MainSearchPtr;
1027                  MainSearchPtr = SquareSearch;                  if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
1028          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
                 MainSearchPtr = AdvDiamondSearch;  
1029                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1030    
1031          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, iDirection);                  (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1032    
1033  /* extended search, diamond starting in 0,0 and in prediction.  /* extended search, diamond starting in 0,0 and in prediction.
1034          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 1036 
1036    
1037          if (MotionFlags & PMV_EXTSEARCH16) {          if (MotionFlags & PMV_EXTSEARCH16) {
1038                  int32_t bSAD;                  int32_t bSAD;
1039                  VECTOR startMV = Data.predMV, backupMV = currentMV[0];                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
1040                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?
1041                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);
1042                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1043                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1044    
1045                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1046                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1047                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1048                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1049                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1050                  }                  }
1051    
1052                  backupMV = currentMV[0];                          backupMV = Data->currentMV[0];
1053                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;
1054                  else startMV.x = startMV.y = 0;                  else startMV.x = startMV.y = 0;
1055                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1056                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1057    
1058                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1059                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1060                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1061                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1062                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1063                            }
1064                  }                  }
1065          }          }
1066    
1067  PMVfast16_Terminate_with_Refine:          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1068    
1069          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          for(i = 0; i < 5; i++) {
1070                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1071                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1072            }
1073    
1074            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1075    
1076  PMVfast16_Terminate_without_Refine:                  CheckCandidate = CheckCandidate16_qpel;
1077                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1078                                    pParam->width, pParam->height, Data->iFcode, 0);
1079    
1080          if (inter4v)                  QuarterpelRefine(Data);
1081                  for(i = 0; i < 4; i++)          }
1082                          Search8(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);  
1083            if (Data->iMinSAD[0] < (int32_t)iQuant * 30 ) inter4v = 0;
1084            if (inter4v) {
1085                    SearchData Data8;
1086                    Data8.iFcode = Data->iFcode;
1087                    Data8.lambda8 = Data->lambda8;
1088                    Data8.iEdgedWidth = Data->iEdgedWidth;
1089                    Data8.RefQ = Data->RefQ;
1090                    Data8.qpel = Data->qpel;
1091                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1092                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1093                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1094                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1095    
1096                    if (Data->chroma) {
1097                            int sum, dx, dy;
1098    
1099                            if(pParam->m_quarterpel) {
1100                                    sum = pMB->qmvs[0].y/2 + pMB->qmvs[1].y/2 + pMB->qmvs[2].y/2 + pMB->qmvs[3].y/2;
1101                            } else sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1102                            dy = (sum >> 3) + roundtab_76[sum & 0xf];
1103    
1104                            if(pParam->m_quarterpel) {
1105                                    sum = pMB->qmvs[0].x/2 + pMB->qmvs[1].x/2 + pMB->qmvs[2].x/2 + pMB->qmvs[3].x/2;
1106                            } else sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1107                            dx = (sum >> 3) + roundtab_76[sum & 0xf];
1108    
1109                            Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);
1110                    }
1111            }
1112    
1113          if (!(inter4v) ||          if (!(inter4v) ||
1114                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
1115                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1116  // INTER MODE  // INTER MODE
1117                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1118                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1119                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1120    
1121                    pMB->qmvs[0] = pMB->qmvs[1]
1122                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1123    
1124                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1125                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1126    
1127                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1128                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predQMV.x;
1129                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predQMV.y;
1130                    } else {
1131                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1132                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1133                    }
1134          } else {          } else {
1135  // INTER4V MODE; all other things are already set in Search8  // INTER4V MODE; all other things are already set in Search8
1136                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1137                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1138                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1139          }          }
   
1140  }  }
1141    
1142  static void  static void
# Line 820  Line 1146 
1146                  const MBParam * const pParam,                  const MBParam * const pParam,
1147                  MACROBLOCK * const pMB,                  MACROBLOCK * const pMB,
1148                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
1149                  const int block)                  const int block,
1150                    SearchData * const Data)
1151  {  {
1152          SearchData Data;          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1153            Data->currentMV = OldData->currentMV + 1 + block;
1154          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          Data->currentQMV = OldData->currentQMV + 1 + block;
1155          Data.iMinSAD = OldData->iMinSAD + 1 + block;  
1156          Data.currentMV = OldData->currentMV+1+block;          if(pParam->m_quarterpel) {
1157          Data.iFcode = OldData->iFcode;                  Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1158          Data.iQuant = OldData->iQuant;                  if (block != 0) *(Data->iMinSAD) += (Data->lambda8 *
1159                                                                            d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1160          if (block != 0)                                                                                                  Data->currentQMV->y - Data->predQMV.y,
1161                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *                                                                                                  Data->iFcode) * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
1162                                                                  d_mv_bits(      Data.currentMV->x - Data.predMV.x,          } else {
1163                                                                                          Data.currentMV->y - Data.predMV.y,                  Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1164                                                                                          Data.iFcode);                  if (block != 0) *(Data->iMinSAD) += (Data->lambda8 *
1165                                                                            d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1166                                                                                                    Data->currentMV->y - Data->predMV.y,
1167                                                                                                    Data->iFcode) * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
1168            }
1169    
1170          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
1171    
1172                  Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));
1173                  Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));
1174                  Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1175                  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));  
1176    
1177                  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);  
1178    
1179                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1180                                    pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1181                  CheckCandidate = CheckCandidate8;                  CheckCandidate = CheckCandidate8;
1182    
1183                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & PMV_EXTSEARCH8) {
1184                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1185    
1186                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1187                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1188                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1189                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1190    
1191                          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);     }                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1192    
1193                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                          if(*(Data->iMinSAD) < temp_sad) {
1194                                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1195                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1196                            }
1197                    }
1198    
1199                    if (MotionFlags & PMV_HALFPELREFINE8) {
1200                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1201    
1202                            HalfpelRefine(Data); // perform halfpel refine of current best vector
1203    
1204                            if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1205                                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1206                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1207                            }
1208                    }
1209    
1210                    if(pParam->m_quarterpel) {
1211                            if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1212                                    (MotionFlags & PMV_QUARTERPELREFINE8)) {
1213                            CheckCandidate = CheckCandidate8_qpel;
1214                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1215                                    pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1216                            QuarterpelRefine(Data);
1217                            }
1218                    }
1219            }
1220    
1221            if(pParam->m_quarterpel) {
1222                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predQMV.x;
1223                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predQMV.y;
1224            }
1225            else {
1226                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1227                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1228          }          }
1229    
1230          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;          pMB->mvs[block] = *(Data->currentMV);
1231          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;          pMB->qmvs[block] = *(Data->currentQMV);
1232          pMB->mvs[block] = *(Data.currentMV);  
1233          pMB->sad8[block] =  4 * (*(Data.iMinSAD));          pMB->sad8[block] =  4 * (*Data->iMinSAD);
1234  }  }
1235    
1236  /* B-frames code starts here */  /* B-frames code starts here */
# Line 896  Line 1258 
1258          pmv[2] = ChoosePred(pMB, mode_curr);          pmv[2] = ChoosePred(pMB, mode_curr);
1259          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);
1260    
         pmv[3].x = pmv[3].y = 0;  
1261          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour
1262                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);
1263                  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);
1264            } else pmv[3].x = pmv[3].y = 0;
1265    
1266          if (y != 0) {          if (y != 0) {
1267                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);
# Line 929  Line 1291 
1291                          const IMAGE * const pCur,                          const IMAGE * const pCur,
1292                          const int x, const int y,                          const int x, const int y,
1293                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
1294                          const uint32_t iFcode,                          const uint32_t iFcode,
1295                          const MBParam * const pParam,                          const MBParam * const pParam,
1296                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
1297                          const VECTOR * const predMV,                          const VECTOR * const predMV,
1298                          int32_t * const best_sad,                          int32_t * const best_sad,
1299                          const int32_t mode_current)                          const int32_t mode_current,
1300                            SearchData * const Data)
1301  {  {
1302    
1303          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1304    
1305          int i, iDirection, mask;          int i, iDirection, mask;
1306          VECTOR currentMV, pmv[7];          VECTOR pmv[7];
1307          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1308          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
1309          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;  
1310    
1311          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,          Data->Ref = pRef + (x + y * iEdgedWidth) * 16;
1312                                  pParam->width, pParam->height, iFcode);          Data->RefH = pRefH + (x + y * iEdgedWidth) * 16;
1313            Data->RefV = pRefV + (x + y * iEdgedWidth) * 16;
1314            Data->RefHV = pRefHV + (x + y * iEdgedWidth) * 16;
1315    
1316          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?  
1317    
1318            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1319                                    pParam->width, pParam->height, iFcode, pParam->m_quarterpel);
1320    
1321          pmv[0] = Data.predMV;          pmv[0] = Data->predMV;
1322          PreparePredictionsBF(pmv, x, y, pParam->mb_width,          PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
                                         pMB, mode_current);  
1323    
1324          currentMV.x = currentMV.y = 0;          Data->currentMV->x = Data->currentMV->y = 0;
1325    
1326          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1327    
1328  // main loop. checking all predictions  // main loop. checking all predictions
1329          for (i = 0; i < 8; i++) {          for (i = 0; i < 8; i++) {
1330                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1331                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1332          }          }
1333    
1334          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 990  Line 1337 
1337                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1338                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1339    
1340          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1341    
1342          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          HalfpelRefine(Data);
1343    
1344  // three bits are needed to code backward mode. four for forward  // three bits are needed to code backward mode. four for forward
1345  // we treat the bits just like they were vector's  // we treat the bits just like they were vector's
1346          if (mode_current == MODE_FORWARD) iMinSAD +=  4 * lambda_vec16[iQuant];          if (mode_current == MODE_FORWARD) *Data->iMinSAD +=  4 * Data->lambda16;
1347          else iMinSAD +=  3 * lambda_vec16[iQuant];          else *Data->iMinSAD +=  3 * Data->lambda16;
1348    
1349            if (*Data->iMinSAD < *best_sad) {
1350          if (iMinSAD < *best_sad) {                  *best_sad = *Data->iMinSAD;
                 *best_sad = iMinSAD;  
1351                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1352                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1353                  pMB->pmvs[0].y = currentMV.y - predMV->y;                  pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1354                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = *(Data->currentMV+2) = *Data->currentMV;
1355                  else pMB->b_mvs[0] = currentMV;                  else pMB->b_mvs[0] = *(Data->currentMV+1) = *Data->currentMV; //we store currmv for interpolate search
1356          }          }
1357    
1358  }  }
1359    
1360  static int32_t  static int32_t
1361  SearchDirect(const uint8_t * const f_Ref,  SearchDirect(const IMAGE * const f_Ref,
1362                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1363                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
1364                                  const uint8_t * const f_RefHV,                                  const uint8_t * const f_RefHV,
1365                                  const uint8_t * const b_Ref,                                  const IMAGE * const b_Ref,
1366                                  const uint8_t * const b_RefH,                                  const uint8_t * const b_RefH,
1367                                  const uint8_t * const b_RefV,                                  const uint8_t * const b_RefV,
1368                                  const uint8_t * const b_RefHV,                                  const uint8_t * const b_RefHV,
1369                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1370                                  const int x, const int y,                                  const int x, const int y,
1371                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1372                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1373                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1374                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1375                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1376                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1377                                    SearchData * const Data)
1378    
1379  {  {
1380          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
         int32_t iMinSAD = 0, skip_sad;  
1381          int k;          int k;
1382          VECTOR currentMV;  
1383          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
         SearchData Data;  
1384    
1385          Data.iMinSAD = &iMinSAD;          *Data->iMinSAD = 256*4096;
1386          Data.Cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;          Data->referencemv = b_mb->mvs;
         Data.iEdgedWidth = iEdgedWidth;  
         Data.currentMV = &currentMV;  
         Data.iQuant = iQuant;  
         Data.referencemv = b_mb->mvs;  
1387    
1388          Data.Ref= f_Ref + (x + iEdgedWidth*y) * 16;          Data->Ref = f_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1389          Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;          Data->RefH = f_RefH + (x + Data->iEdgedWidth*y) * 16;
1390          Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;          Data->RefV = f_RefV + (x + Data->iEdgedWidth*y) * 16;
1391          Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = f_RefHV + (x + Data->iEdgedWidth*y) * 16;
1392          Data.bRef = b_Ref + (x + iEdgedWidth*y) * 16;          Data->bRef = b_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1393          Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;          Data->bRefH = b_RefH + (x + Data->iEdgedWidth*y) * 16;
1394          Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;          Data->bRefV = b_RefV + (x + Data->iEdgedWidth*y) * 16;
1395          Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;          Data->bRefHV = b_RefHV + (x + Data->iEdgedWidth*y) * 16;
1396  /*  
1397  //What we do here is a complicated version of CheckCandidateDirect(0,0);          Data->max_dx = 2 * pParam->width - 2 * (x) * 16;
1398  get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16, pParam->width, pParam->height, 19);          Data->max_dy = 2 * pParam->height - 2 * (y) * 16;
1399            Data->min_dx = -(2 * 16 + 2 * (x) * 16);
1400  */          Data->min_dy = -(2 * 16 + 2 * (y) * 16);
         Data.max_dx = 2 * pParam->width - 2 * (x) * 16;  
         Data.max_dy = 2 * pParam->height - 2 * (y) * 16;  
         Data.min_dx = -(2 * 16 + 2 * (x) * 16);  
         Data.min_dy = -(2 * 16 + 2 * (y) * 16);  
1401    
1402          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1403                  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);
1404                  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;
1405                  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);
1406                  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; }  
1407    
1408                    if ( ( pMB->b_mvs[k].x > Data->max_dx ) || ( pMB->b_mvs[k].x < Data->min_dx )
1409                            || ( pMB->b_mvs[k].y > Data->max_dy ) || ( pMB->b_mvs[k].y < Data->min_dy )) {
1410    
1411                            *best_sad = 256*4096; // in that case, we won't use direct mode
1412                            pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
1413                            pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;
1414                            return 0;
1415                    }
1416          if (b_mb->mode != MODE_INTER4V) {          if (b_mb->mode != MODE_INTER4V) {
1417                  iMinSAD = sad16bi(Data.Cur,                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1418                                                  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];
1419                                                                  x, y, 16, &pMB->mvs[0], iEdgedWidth),                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1420                                                  get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1421                                                                  x, y, 16, &pMB->b_mvs[0], iEdgedWidth), iEdgedWidth);                          break;
1422                    }
                 Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];  
                 Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];  
                 break;  
         }  
         iMinSAD += sad8bi(Data.Cur + (k&1)*8 + (k>>1)* 8 * iEdgedWidth,  
                                                 get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,  
                                                                 (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->mvs[k], iEdgedWidth),  
                                                 get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,  
                                                                 (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->b_mvs[k], iEdgedWidth),  
                                                 iEdgedWidth);  
1423          }          }
1424    
 // skip decision  
         if (iMinSAD < (int32_t)iQuant * SKIP_THRESH_B) {  
                 pMB->mode = MODE_DIRECT_NONE_MV;  
                 return iMinSAD; }  
   
         skip_sad = iMinSAD;  
         iMinSAD += 2 * lambda_vec16[iQuant]; // 2 bits needed to code vector 0,0  
         currentMV.x = currentMV.y = 0;  
1425          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1426                  CheckCandidate = CheckCandidateDirect;                  CheckCandidate = CheckCandidateDirect;
1427          else CheckCandidate = CheckCandidateDirectno4v;          else CheckCandidate = CheckCandidateDirectno4v;
1428    
1429            (*CheckCandidate)(0, 0, 255, &k, Data);
1430    
1431    // skip decision
1432            if (*Data->iMinSAD < pMB->quant * SKIP_THRESH_B) {
1433                    //possible skip - checking chroma. everything copied from MC
1434                    //this is not full chroma compensation, only it's fullpel approximation. should work though
1435                    int sum, dx, dy, b_dx, b_dy;
1436    
1437                    sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1438                    dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1439    
1440                    sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1441                    dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1442    
1443                    sum = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;
1444                    b_dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1445    
1446                    sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;
1447                    b_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1448    
1449                    sum = sad8bi(pCur->u + 8*x + 8*y*(Data->iEdgedWidth/2),
1450                                            f_Ref->u + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1451                                            b_Ref->u + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1452                                            Data->iEdgedWidth/2);
1453                    sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1454                                            f_Ref->v + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1455                                            b_Ref->v + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1456                                            Data->iEdgedWidth/2);
1457    
1458                    if (sum < MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) {
1459                            pMB->mode = MODE_DIRECT_NONE_MV;
1460                            return *Data->iMinSAD;
1461                    }
1462            }
1463    
1464            skip_sad = *Data->iMinSAD;
1465    
1466  //  DIRECT MODE DELTA VECTOR SEARCH.  //  DIRECT MODE DELTA VECTOR SEARCH.
1467  //      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
1468    
# Line 1123  Line 1470 
1470                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1471                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1472    
1473          (*MainSearchPtr)(0, 0, &Data, 255);          (*MainSearchPtr)(0, 0, Data, 255);
1474    
1475          HalfpelRefine(&Data);          HalfpelRefine(Data);
1476    
1477          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
1478          *best_sad = iMinSAD;          *best_sad = *Data->iMinSAD;
1479    
1480          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1481                  pMB->mode = MODE_DIRECT;                  pMB->mode = MODE_DIRECT;
1482          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1483    
1484          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1485    
1486          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1487                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1488                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = ((Data->currentMV->x == 0)
1489                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1490                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          : pMB->mvs[k].x - Data->referencemv[k].x);
1491                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1492                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1493                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1494                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1495                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1496                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1497                          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];
1498                          break;                          break;
1499                  }                  }
1500          }          }
1501          return 0;//skip_sad;          return skip_sad;
1502  }  }
1503    
1504    
1505  static __inline void  static __inline void
1506  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const uint8_t * const f_Ref,
1507                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
# Line 1168  Line 1516 
1516                                  const uint32_t fcode,                                  const uint32_t fcode,
1517                                  const uint32_t bcode,                                  const uint32_t bcode,
1518                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1519                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1520                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1521                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1522                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1523                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1524                                    SearchData * const fData)
1525    
1526  {  {
 /* 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". */  
1527    
1528          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1529    
1530          int iDirection, i, j;          int iDirection, i, j;
1531          int32_t iMinSAD = 256*4096;          SearchData bData;
         VECTOR currentMV[3];  
         SearchData fData, bData;  
1532    
1533            *(bData.iMinSAD = fData->iMinSAD) = 4096*256;
1534            bData.Cur = fData->Cur;
1535            fData->iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;
1536            bData.currentMV = fData->currentMV + 1;
1537            bData.lambda16 = fData->lambda16;
1538            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1539    
1540            bData.bRef = fData->Ref = f_Ref + (x + y * iEdgedWidth) * 16;
1541            bData.bRefH = fData->RefH = f_RefH + (x + y * iEdgedWidth) * 16;
1542            bData.bRefV = fData->RefV = f_RefV + (x + y * iEdgedWidth) * 16;
1543            bData.bRefHV = fData->RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;
1544            bData.Ref = fData->bRef = b_Ref + (x + y * iEdgedWidth) * 16;
1545            bData.RefH = fData->bRefH = b_RefH + (x + y * iEdgedWidth) * 16;
1546            bData.RefV = fData->bRefV = b_RefV + (x + y * iEdgedWidth) * 16;
1547            bData.RefHV = fData->bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;
1548    
1549            bData.bpredMV = fData->predMV = *f_predMV;
1550            fData->bpredMV = bData.predMV = *b_predMV;
1551    
1552            fData->currentMV[0] = fData->currentMV[3]; //forward search stored it's vector here. backward stored it in the place it's needed
1553            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);
1554            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);
1555    
1556            if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1557            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dy;
1558            if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dx;
1559            if (fData->currentMV[0].y > fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1560    
1561            if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1562            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dy;
1563            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dx;
1564            if (fData->currentMV[1].y > bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1565    
1566          fData.iMinSAD = bData.iMinSAD = &iMinSAD;          CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
   
         fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
         fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;  
         fData.currentMV = currentMV; bData.currentMV = currentMV + 1;  
         fData.iQuant = bData.iQuant = iQuant;  
         fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;  
   
   
         bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  
         bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;  
         bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;  
         bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;  
         bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;  
         bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;  
         bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;  
         bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;  
   
         bData.bpredMV = fData.predMV = *f_predMV;  
         fData.bpredMV = bData.predMV = *b_predMV;  
   
   
         currentMV[0] = pMB->mvs[0];  
         currentMV[1] = pMB->b_mvs[0];  
         get_range(&fData.min_dx, &fData.max_dx, &fData.min_dy, &fData.max_dy, x, y, 16, pParam->width, pParam->height, fcode);  
         get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode);  
   
         CheckCandidateInt(currentMV[0].x, currentMV[0].y, 255, &iDirection, &fData);  
1567    
1568  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)
1569    
1570          do {          do {
1571                  iDirection = 255;                  iDirection = 255;
1572                  // forward MV moves                  // forward MV moves
1573                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
1574    
1575                  CheckCandidateInt(i + 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1576                  CheckCandidateInt(i, j + 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1577                  CheckCandidateInt(i - 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1578                  CheckCandidateInt(i, j - 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
1579    
1580                  // backward MV moves                  // backward MV moves
1581                  i = currentMV[1].x; j = currentMV[1].y;                  i = fData->currentMV[1].x; j = fData->currentMV[1].y;
1582                  currentMV[2] = currentMV[0];                  fData->currentMV[2] = fData->currentMV[0];
1583    
1584                  CheckCandidateInt(i + 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1585                  CheckCandidateInt(i, j + 2, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1586                  CheckCandidateInt(i - 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
1587                  CheckCandidateInt(i, j - 2, 0, &iDirection, &bData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, &bData);
1588    
1589          } while (!(iDirection));          } while (!(iDirection));
1590    
1591  /* halfpel refinement. luckly we can use normal halfpel function for it */          *fData->iMinSAD +=  2 * fData->lambda16; // two bits are needed to code interpolate mode.
1592    
1593          if (MotionFlags & PMV_HALFPELREFINE16) {          if (*fData->iMinSAD < *best_sad) {
1594                  CheckCandidate = CheckCandidateInt;                  *best_sad = *fData->iMinSAD;
1595                  HalfpelRefine(&fData);                  pMB->mvs[0] = fData->currentMV[0];
1596                  currentMV[2] = currentMV[0];                  pMB->b_mvs[0] = fData->currentMV[1];
                 HalfpelRefine(&bData);  
         }  
   
 // two bits are needed to code interpolate mode. we treat the bits just like they were vector's  
         iMinSAD +=  2 * lambda_vec16[iQuant];  
         if (iMinSAD < *best_sad) {  
                 *best_sad = iMinSAD;  
                 pMB->mvs[0] = currentMV[0];  
                 pMB->b_mvs[0] = currentMV[1];  
1597                  pMB->mode = MODE_INTERPOLATE;                  pMB->mode = MODE_INTERPOLATE;
1598    
1599                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;
# Line 1277  Line 1615 
1615                                           const IMAGE * const f_refV,                                           const IMAGE * const f_refV,
1616                                           const IMAGE * const f_refHV,                                           const IMAGE * const f_refHV,
1617                                           // backward (future) reference                                           // backward (future) reference
1618                                           const MACROBLOCK * const b_mbs,                                           const FRAMEINFO * const b_reference,
1619                                           const IMAGE * const b_ref,                                           const IMAGE * const b_ref,
1620                                           const IMAGE * const b_refH,                                           const IMAGE * const b_refH,
1621                                           const IMAGE * const b_refV,                                           const IMAGE * const b_refV,
# Line 1287  Line 1625 
1625          int32_t best_sad, skip_sad;          int32_t best_sad, skip_sad;
1626          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;
1627          static const VECTOR zeroMV={0,0};          static const VECTOR zeroMV={0,0};
1628            const MACROBLOCK * const b_mbs = b_reference->mbs;
1629    
1630          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
1631    
1632          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1633          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
1634    
1635    // some pre-inintialized data for the rest of the search
1636    
1637            SearchData Data;
1638            int32_t iMinSAD;
1639            VECTOR currentMV[3];
1640            Data.iEdgedWidth = pParam->edged_width;
1641            Data.currentMV = currentMV;
1642            Data.iMinSAD = &iMinSAD;
1643            Data.lambda16 = lambda_vec16[frame->quant];
1644    
1645          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
1646    
1647          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
# Line 1303  Line 1652 
1652                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;
1653                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;
1654    
1655  /* 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 */
1656                            if (b_reference->coding_type != S_VOP)
1657                          if (b_mb->mode == MODE_NOT_CODED) {                          if (b_mb->mode == MODE_NOT_CODED) {
1658                                  pMB->mode = MODE_NOT_CODED;                                  pMB->mode = MODE_NOT_CODED;
1659                                  continue;                                  continue;
1660                          }                          }
1661    
1662                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
1663                            pMB->quant = frame->quant;
1664    
1665  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
1666          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
1667                            skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
1668                          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,  
1669                                                                          &frame->image,                                                                          &frame->image,
1670                                                                          i, j,                                                                          i, j,
1671                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
1672                                                                          TRB, TRD,                                                                          TRB, TRD,
1673                                                                          pParam,                                                                          pParam,
1674                                                                          pMB, b_mb,                                                                          pMB, b_mb,
1675                                                                          &best_sad);                                                                          &best_sad,
1676                                                                            &Data);
1677    
                         if (!(frame->global_flags & XVID_HALFPEL)) best_sad = skip_sad = 256*4096;  
                         else  
1678                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1679    
 //                      best_sad = 256*4096; //uncomment to disable Directsearch.  
 //      To disable any other mode, just comment the function call  
   
1680                          // forward search                          // forward search
1681                          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,
1682                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1683                                                  frame->motion_flags,                                                  frame->motion_flags,
1684                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
1685                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
1686                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
1687    
1688                          // backward search                          // backward search
1689                          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,
1690                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1691                                                  frame->motion_flags,                                                  frame->motion_flags,
1692                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
1693                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
1694                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
1695    
1696                          // 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
1697    
# Line 1354  Line 1701 
1701                                                  i, j,                                                  i, j,
1702                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
1703                                                  frame->motion_flags,                                                  frame->motion_flags,
1704                                                  frame->quant, pParam,                                                  pParam,
1705                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
1706                                                  pMB, &best_sad);                                                  pMB, &best_sad,
1707                                                    &Data);
1708    
1709                          switch (pMB->mode) {                          switch (pMB->mode) {
1710                                  case MODE_FORWARD:                                  case MODE_FORWARD:
# Line 1381  Line 1729 
1729                          }                          }
1730                  }                  }
1731          }          }
   
 //      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);  
   
1732  }  }
1733    
1734  /* Hinted ME starts here */  /* Hinted ME starts here */
1735    
 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));  
 }  
   
   
1736  static void  static void
1737  SearchPhinted ( const uint8_t * const pRef,  SearchPhinted ( const IMAGE * const pRef,
1738                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
1739                                  const uint8_t * const pRefV,                                  const uint8_t * const pRefV,
1740                                  const uint8_t * const pRefHV,                                  const uint8_t * const pRefHV,
# Line 1455  Line 1743 
1743                                  const int y,                                  const int y,
1744                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1745                                  const uint32_t iQuant,                                  const uint32_t iQuant,
                                 const uint32_t iFcode,  
1746                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1747                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1748                                  int inter4v,                                  int inter4v,
1749                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
1750                                    SearchData * const Data)
1751  {  {
1752    
1753          const int32_t iEdgedWidth = pParam->edged_width;          int i, t;
   
         int i;  
         VECTOR currentMV[5];  
         int32_t iMinSAD[5];  
         int32_t temp[5];  
1754          MainSearchFunc * MainSearchPtr;          MainSearchFunc * MainSearchPtr;
         SearchData Data;  
1755    
1756          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1757          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,          Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1758                                  pParam->width, pParam->height, iFcode);          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1759                                    pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
1760          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
1761          Data.iEdgedWidth = iEdgedWidth;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
1762          Data.currentMV = currentMV;          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1763          Data.iMinSAD = iMinSAD;          Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1764          Data.Ref = pRef + (x + iEdgedWidth*y)*16;  
1765          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16;
1766          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
1767          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
1768          Data.temp = temp;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
1769          Data.iQuant = iQuant;          Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1770          Data.iFcode = iFcode;          Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1771    
1772          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
1773                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
1774                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
1775                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
1776                  Data.max_dy = EVEN(Data.max_dy);                  Data->max_dy = EVEN(Data->max_dy);
1777          }          }
1778    
1779          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;          for(i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
1780    
1781          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
1782    
1783          if (inter4v)          if (inter4v || pParam->m_quarterpel || Data->chroma) CheckCandidate = CheckCandidate16;
                 CheckCandidate = CheckCandidate16;  
1784          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
1785    
   
1786          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);
1787          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);
1788          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
1789          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;
1790          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;
1791          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;
1792    
1793          CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);          (*CheckCandidate)(pMB->mvs[0].x, pMB->mvs[0].y, 0, &t, Data);
1794    
1795          if (pMB->mode == MODE_INTER4V)          if (pMB->mode == MODE_INTER4V)
1796                  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
1797                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);
1798                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);
1799                          if (!(make_mask(pMB->mvs, i)))                          if (!(make_mask(pMB->mvs, i)))
1800                                  CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);                                  (*CheckCandidate)(pMB->mvs[i].x, pMB->mvs[i].y, 0, &t, Data);
1801                  }                  }
1802    
1803          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1526  Line 1806 
1806                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1807                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1808    
1809          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1810    
1811          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1812    
1813          if (inter4v)          for(i = 0; i < 5; i++) {
1814                  for(i = 0; i < 4; i++)                  Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1815                          Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                  Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1816            }
1817    
1818            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1819                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1820                                    pParam->width, pParam->height, Data->iFcode, 0);
1821                    CheckCandidate = CheckCandidate16_qpel;
1822                    QuarterpelRefine(Data);
1823            }
1824    
1825            if (inter4v) {
1826                    SearchData Data8;
1827                    Data8.iFcode = Data->iFcode;
1828                    Data8.lambda8 = Data->lambda8;
1829                    Data8.iEdgedWidth = Data->iEdgedWidth;
1830                    Data8.RefQ = Data->RefQ;
1831                    Data8.qpel = Data->qpel;
1832                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1833                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1834                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1835                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1836    
1837                    if (Data->chroma) {
1838                            int sum, dx, dy;
1839    
1840                            if(pParam->m_quarterpel)
1841                                    sum = (pMB->qmvs[0].y + pMB->qmvs[1].y + pMB->qmvs[2].y + pMB->qmvs[3].y)/2;
1842                            else sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1843                            dy = (sum ? SIGN(sum) *
1844                                      (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2) : 0);
1845    
1846                            if(pParam->m_quarterpel)
1847                                    sum = (pMB->qmvs[0].x + pMB->qmvs[1].x + pMB->qmvs[2].x + pMB->qmvs[3].x)/2;
1848                            else sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1849                            dx = (sum ? SIGN(sum) *
1850                                      (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2) : 0);
1851                            Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);
1852                    }
1853            }
1854    
1855          if (!(inter4v) ||          if (!(inter4v) ||
1856                  (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] +
1857                                                            Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1858  // INTER MODE  // INTER MODE
   
1859                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1860                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1861                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1862    
1863                    pMB->qmvs[0] = pMB->qmvs[1]
1864                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1865    
1866                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1867                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1868    
1869                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1870                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predQMV.x;
1871                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predQMV.y;
1872                    } else {
1873                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1874                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1875                    }
1876          } else {          } else {
1877  // INTER4V MODE; all other things are already set in Search8hinted  // INTER4V MODE; all other things are already set in Search8
1878                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1879                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3]
1880                                                    + Data->iMinSAD[4] + IMV16X16 * iQuant;
1881          }          }
1882    
1883  }  }
# Line 1568  Line 1895 
1895          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
1896    
1897          uint32_t x, y;          uint32_t x, y;
1898            uint8_t * qimage;
1899            int32_t temp[5], quant = current->quant;
1900            int32_t iMinSAD[5];
1901            VECTOR currentMV[5], currentQMV[5];
1902            SearchData Data;
1903            Data.iEdgedWidth = pParam->edged_width;
1904            Data.currentMV = currentMV;
1905            Data.currentQMV = currentQMV;
1906            Data.iMinSAD = iMinSAD;
1907            Data.temp = temp;
1908            Data.iFcode = current->fcode;
1909            Data.rounding = pParam->m_rounding_type;
1910            Data.qpel = pParam->m_quarterpel;
1911            Data.chroma = current->global_flags & XVID_ME_COLOUR;
1912    
1913            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
1914                    return; // allocate some mem for qpel interpolated blocks
1915                                      // somehow this is dirty since I think we shouldn't use malloc outside
1916                                      // encoder_create() - so please fix me!
1917    
1918            Data.RefQ = qimage;
1919    
1920          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
1921    
1922          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
1923                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
                         int32_t sad00;  
1924    
1925                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
1926    
# Line 1583  Line 1930 
1930                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
1931                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
1932                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant; }
1933                            else {
1934                                    if (pMB->dquant != NO_CHANGE) {
1935                                            quant += DQtab[pMB->dquant];
1936                                            if (quant > 31) quant = 31;
1937                                            else if (quant < 1) quant = 1;
1938                                    }
1939                                    pMB->quant = quant;
1940                            }
1941    
1942                          if (pMB->dquant == NO_CHANGE) //no skip otherwise, anyway                          SearchPhinted(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
1943                                  sad00 = pMB->sad16                                                          y, current->motion_flags, pMB->quant,
1944                                          = sad16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
1945                                                                  pRef->y + (x + y * pParam->edged_width) * 16,                                                          &Data);
                                                                 pParam->edged_width, 256*4096 );  
                         else sad00 = 256*4096;  
1946    
1947                    }
1948            }
1949            free(qimage);
1950    }
1951    
1952  //initial skip decision  static __inline int
1953    MEanalyzeMB (   const uint8_t * const pRef,
1954                                    const uint8_t * const pCur,
1955                                    const int x,
1956                                    const int y,
1957                                    const MBParam * const pParam,
1958                                    const MACROBLOCK * const pMBs,
1959                                    MACROBLOCK * const pMB,
1960                                    SearchData * const Data)
1961    {
1962    
1963                          if ( (pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)          int i = 255, mask;
1964                                  && ( //(pMB->mode == MODE_NOT_CODED) ||          VECTOR pmv[3];
1965                                          (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant) )) ) {          *(Data->iMinSAD) = MV_MAX_ERROR;
1966                                  if (sad00 < pMB->quant * INITIAL_SKIP_THRESH) {  
1967                                          SkipMacroblockP(pMB, sad00);          //median is only used as prediction. it doesn't have to be real
1968                                          continue; } //skipped          if (x == 1 && y == 1) Data->predMV.x = Data->predMV.y = 0;
1969            else
1970                    if (x == 1) //left macroblock does not have any vector now
1971                            Data->predMV = (pMB - pParam->mb_width)->mvs[0]; // top instead of median
1972                    else if (y == 1) // top macroblock don't have it's vector
1973                            Data->predMV = (pMB - 1)->mvs[0]; // left instead of median
1974                            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); //else median
1975    
1976            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1977                                    pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
1978    
1979            Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
1980            Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
1981    
1982            pmv[1].x = EVEN(pMB->mvs[0].x);
1983            pmv[1].y = EVEN(pMB->mvs[0].y);
1984            pmv[2].x = EVEN(Data->predMV.x);
1985            pmv[2].y = EVEN(Data->predMV.y);
1986            pmv[0].x = pmv[0].y = 0;
1987    
1988            (*CheckCandidate)(0, 0, 255, &i, Data);
1989    
1990    //early skip for 0,0
1991            if (*Data->iMinSAD < MAX_SAD00_FOR_SKIP * 4) {
1992                    pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1993                    pMB->mode = MODE_NOT_CODED;
1994                    return 0;
1995                          }                          }
                         else sad00 = 256*4096;  
1996    
1997                          if (pMB->mode == MODE_NOT_CODED)          if (!(mask = make_mask(pmv, 1)))
1998                                  SearchP(        pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                  (*CheckCandidate)(pmv[1].x, pmv[1].y, mask, &i, Data);
1999                                                          y, current->motion_flags, pMB->quant,          if (!(mask = make_mask(pmv, 2)))
2000                                                          current->fcode, pParam, pMBs, reference->mbs,                  (*CheckCandidate)(pmv[2].x, pmv[2].y, mask, &i, Data);
2001                                                          current->global_flags & XVID_INTER4V, pMB);  
2002            if (*Data->iMinSAD > MAX_SAD00_FOR_SKIP * 4) // diamond only if needed
2003                    DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
2004    
2005            pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
2006            pMB->mode = MODE_INTER;
2007            return *(Data->iMinSAD);
2008    }
2009    
2010    #define INTRA_THRESH    1350
2011    #define INTER_THRESH    900
2012    
2013    
2014    int
2015    MEanalysis(     const IMAGE * const pRef,
2016                            FRAMEINFO * const Current,
2017                            MBParam * const pParam,
2018                            int maxIntra, //maximum number if non-I frames
2019                            int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame
2020                            int bCount) // number if B frames in a row
2021    {
2022            uint32_t x, y, intra = 0;
2023            int sSAD = 0;
2024            MACROBLOCK * const pMBs = Current->mbs;
2025            const IMAGE * const pCurrent = &Current->image;
2026            int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH;
2027    
2028            VECTOR currentMV;
2029            int32_t iMinSAD;
2030            SearchData Data;
2031            Data.iEdgedWidth = pParam->edged_width;
2032            Data.currentMV = &currentMV;
2033            Data.iMinSAD = &iMinSAD;
2034            Data.iFcode = Current->fcode;
2035            CheckCandidate = CheckCandidate16no4vI;
2036    
2037            if (intraCount < 12) // we're right after an I frame
2038                    IntraThresh += 4 * (intraCount - 12) * (intraCount - 12);
2039                          else                          else
2040                                  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
2041                                                          y, current->motion_flags, pMB->quant,                          IntraThresh -= (IntraThresh * (maxIntra - 5*(maxIntra - intraCount)))/maxIntra;
                                                         current->fcode, pParam, pMBs,  
                                                         current->global_flags & XVID_INTER4V, pMB);  
2042    
 /* 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);  
2043    
2044            InterThresh += 300 * (1 - bCount);
2045            if (InterThresh < 200) InterThresh = 200;
2046    
2047            if (sadInit) (*sadInit) ();
2048    
2049            for (y = 1; y < pParam->mb_height-1; y++) {
2050                    for (x = 1; x < pParam->mb_width-1; x++) {
2051                            int sad, dev;
2052                            MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2053    
2054                            sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
2055                                                                    pParam, pMBs, pMB, &Data);
2056    
2057                            if (sad > IntraThresh) {
2058                                    dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
2059                                                              pParam->edged_width);
2060                                    if (dev + IntraThresh < sad) {
2061                                            pMB->mode = MODE_INTRA;
2062                                            if (++intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame
2063                  }                  }
2064          }          }
2065                            sSAD += sad;
2066  }  }
2067            }
2068            sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2069            if (sSAD > InterThresh ) return 1; //P frame
2070            emms();
2071            return 0; // B frame
2072    
2073    }
2074    
2075    int
2076    FindFcode(      const MBParam * const pParam,
2077                            const FRAMEINFO * const current)
2078    {
2079            uint32_t x, y;
2080            int max = 0, min = 0, i;
2081    
2082            for (y = 0; y < pParam->mb_height; y++) {
2083                    for (x = 0; x < pParam->mb_width; x++) {
2084    
2085                            MACROBLOCK *pMB = &current->mbs[x + y * pParam->mb_width];
2086                            for(i = 0; i < (pMB->mode == MODE_INTER4V ? 4:1); i++) {
2087                                    if (pMB->mvs[i].x > max) max = pMB->mvs[i].x;
2088                                    if (pMB->mvs[i].y > max) max = pMB->mvs[i].y;
2089    
2090                                    if (pMB->mvs[i].x < min) min = pMB->mvs[i].x;
2091                                    if (pMB->mvs[i].y < min) min = pMB->mvs[i].y;
2092                            }
2093                    }
2094            }
2095    
2096            min = -min;
2097            max += 1;
2098            if (min > max) max = min;
2099            if (pParam->m_quarterpel) max *= 2;
2100    
2101            for (i = 1; (max > 32 << (i - 1)); i++);
2102            return i;
2103    }
2104    
2105    static void
2106    CheckGMC(int x, int y, const int dir, int * iDirection,
2107                    const MACROBLOCK * const pMBs, uint32_t * bestcount, VECTOR * GMC,
2108                    const MBParam * const pParam)
2109    {
2110            uint32_t mx, my, a, count = 0;
2111    
2112            for (my = 1; my < pParam->mb_height-1; my++)
2113                    for (mx = 1; mx < pParam->mb_width-1; mx++) {
2114                            VECTOR mv;
2115                            const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2116                            if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED) continue;
2117                            mv = pMB->mvs[0];
2118                            a = ABS(mv.x - x) + ABS(mv.y - y);
2119                            if (a < 6) count += 6 - a;
2120                    }
2121    
2122            if (count > *bestcount) {
2123                    *bestcount = count;
2124                    *iDirection = dir;
2125                    GMC->x = x; GMC->y = y;
2126            }
2127    }
2128    
2129    
2130    static VECTOR
2131    GlobalMotionEst(const MACROBLOCK * const pMBs, const MBParam * const pParam, const uint32_t iFcode)
2132    {
2133    
2134            uint32_t count, bestcount = 0;
2135            int x, y;
2136            VECTOR gmc = {0,0};
2137            int step, min_x, max_x, min_y, max_y;
2138            uint32_t mx, my;
2139            int iDirection, bDirection;
2140    
2141            min_x = min_y = -32<<iFcode;
2142            max_x = max_y = 32<<iFcode;
2143    
2144    //step1: let's find a rough camera panning
2145            for (step = 32; step >= 2; step /= 2) {
2146                    bestcount = 0;
2147                    for (y = min_y; y <= max_y; y += step)
2148                            for (x = min_x ; x <= max_x; x += step) {
2149                                    count = 0;
2150                                    //for all macroblocks
2151                                    for (my = 1; my < pParam->mb_height-1; my++)
2152                                            for (mx = 1; mx < pParam->mb_width-1; mx++) {
2153                                                    const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2154                                                    VECTOR mv;
2155    
2156                                                    if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
2157                                                            continue;
2158    
2159                                                    mv = pMB->mvs[0];
2160                                                    if ( ABS(mv.x - x) <= step && ABS(mv.y - y) <= step )   /* GMC translation is always halfpel-res */
2161                                                            count++;
2162                                            }
2163                                    if (count >= bestcount) { bestcount = count; gmc.x = x; gmc.y = y; }
2164                            }
2165                    min_x = gmc.x - step;
2166                    max_x = gmc.x + step;
2167                    min_y = gmc.y - step;
2168                    max_y = gmc.y + step;
2169    
2170            }
2171    
2172            if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10)
2173                    gmc.x = gmc.y = 0; //no camara pan, no GMC
2174    
2175    // step2: let's refine camera panning using gradiend-descent approach.
2176    // TODO: more warping points may be evaluated here (like in interpolate mode search - two vectors in one diamond)
2177            bestcount = 0;
2178            CheckGMC(gmc.x, gmc.y, 255, &iDirection, pMBs, &bestcount, &gmc, pParam);
2179            do {
2180                    x = gmc.x; y = gmc.y;
2181                    bDirection = iDirection; iDirection = 0;
2182                    if (bDirection & 1) CheckGMC(x - 1, y, 1+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2183                    if (bDirection & 2) CheckGMC(x + 1, y, 2+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2184                    if (bDirection & 4) CheckGMC(x, y - 1, 1+2+4, &iDirection, pMBs, &bestcount, &gmc, pParam);
2185                    if (bDirection & 8) CheckGMC(x, y + 1, 1+2+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2186    
2187            } while (iDirection);
2188    
2189            if (pParam->m_quarterpel) {
2190                    gmc.x *= 2;
2191                    gmc.y *= 2;     /* we store the halfpel value as pseudo-qpel to make comparison easier */
2192            }
2193    
2194            return gmc;
2195    }

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

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