[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 639, Mon Nov 11 08:42:35 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          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;                          HalfpelRefine(Data); // perform halfpel refine of current best vector
1203          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;  
1204          pMB->mvs[block] = *(Data.currentMV);                          if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1205          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                                  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->mvs[block] = *(Data->currentMV);
1231            pMB->qmvs[block] = *(Data->currentQMV);
1232    
1233            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;  
   
   
         fData.iMinSAD = bData.iMinSAD = &iMinSAD;  
   
         fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
         fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;  
         fData.currentMV = currentMV; bData.currentMV = currentMV + 1;  
         fData.iQuant = bData.iQuant = iQuant;  
         fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;  
   
   
         bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  
         bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;  
         bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;  
         bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;  
         bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;  
         bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;  
         bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;  
         bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;  
1532    
1533          bData.bpredMV = fData.predMV = *f_predMV;          *(bData.iMinSAD = fData->iMinSAD) = 4096*256;
1534          fData.bpredMV = bData.predMV = *b_predMV;          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            CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
         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.
   
         if (MotionFlags & PMV_HALFPELREFINE16) {  
                 CheckCandidate = CheckCandidateInt;  
                 HalfpelRefine(&fData);  
                 currentMV[2] = currentMV[0];  
                 HalfpelRefine(&bData);  
         }  
1592    
1593  // two bits are needed to code interpolate mode. we treat the bits just like they were vector's          if (*fData->iMinSAD < *best_sad) {
1594          iMinSAD +=  2 * lambda_vec16[iQuant];                  *best_sad = *fData->iMinSAD;
1595          if (iMinSAD < *best_sad) {                  pMB->mvs[0] = fData->currentMV[0];
1596                  *best_sad = iMinSAD;                  pMB->b_mvs[0] = fData->currentMV[1];
                 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 1293  Line 1631 
1631          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1632          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
1633    
1634    // some pre-inintialized data for the rest of the search
1635    
1636            SearchData Data;
1637            int32_t iMinSAD;
1638            VECTOR currentMV[3];
1639            Data.iEdgedWidth = pParam->edged_width;
1640            Data.currentMV = currentMV;
1641            Data.iMinSAD = &iMinSAD;
1642            Data.lambda16 = lambda_vec16[frame->quant];
1643    
1644          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
1645    
1646          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
# Line 1303  Line 1651 
1651                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;
1652                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;
1653    
1654  /* 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 */
1655                          if (b_mb->mode == MODE_NOT_CODED) {                          if (b_mb->mode == MODE_NOT_CODED) {
1656                                  pMB->mode = MODE_NOT_CODED;                                  pMB->mode = MODE_NOT_CODED;
1657                                  continue;                                  continue;
1658                          }                          }
1659    
1660                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
1661                            pMB->quant = frame->quant;
1662    
1663  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
1664          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
1665                            skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
1666                          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,  
1667                                                                          &frame->image,                                                                          &frame->image,
1668                                                                          i, j,                                                                          i, j,
1669                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
1670                                                                          TRB, TRD,                                                                          TRB, TRD,
1671                                                                          pParam,                                                                          pParam,
1672                                                                          pMB, b_mb,                                                                          pMB, b_mb,
1673                                                                          &best_sad);                                                                          &best_sad,
1674                                                                            &Data);
1675    
                         if (!(frame->global_flags & XVID_HALFPEL)) best_sad = skip_sad = 256*4096;  
                         else  
1676                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1677    
 //                      best_sad = 256*4096; //uncomment to disable Directsearch.  
 //      To disable any other mode, just comment the function call  
   
1678                          // forward search                          // forward search
1679                          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,
1680                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1681                                                  frame->motion_flags,                                                  frame->motion_flags,
1682                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
1683                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
1684                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
1685    
1686                          // backward search                          // backward search
1687                          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,
1688                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1689                                                  frame->motion_flags,                                                  frame->motion_flags,
1690                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
1691                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
1692                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
1693    
1694                          // 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
1695    
# Line 1354  Line 1699 
1699                                                  i, j,                                                  i, j,
1700                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
1701                                                  frame->motion_flags,                                                  frame->motion_flags,
1702                                                  frame->quant, pParam,                                                  pParam,
1703                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
1704                                                  pMB, &best_sad);                                                  pMB, &best_sad,
1705                                                    &Data);
1706    
1707                          switch (pMB->mode) {                          switch (pMB->mode) {
1708                                  case MODE_FORWARD:                                  case MODE_FORWARD:
# Line 1381  Line 1727 
1727                          }                          }
1728                  }                  }
1729          }          }
   
 //      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);  
   
1730  }  }
1731    
1732  /* Hinted ME starts here */  /* Hinted ME starts here */
1733    
 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));  
 }  
   
   
1734  static void  static void
1735  SearchPhinted ( const uint8_t * const pRef,  SearchPhinted ( const IMAGE * const pRef,
1736                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
1737                                  const uint8_t * const pRefV,                                  const uint8_t * const pRefV,
1738                                  const uint8_t * const pRefHV,                                  const uint8_t * const pRefHV,
# Line 1455  Line 1741 
1741                                  const int y,                                  const int y,
1742                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1743                                  const uint32_t iQuant,                                  const uint32_t iQuant,
                                 const uint32_t iFcode,  
1744                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1745                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1746                                  int inter4v,                                  int inter4v,
1747                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
1748                                    SearchData * const Data)
1749  {  {
1750    
1751          const int32_t iEdgedWidth = pParam->edged_width;          int i, t;
   
         int i;  
         VECTOR currentMV[5];  
         int32_t iMinSAD[5];  
         int32_t temp[5];  
1752          MainSearchFunc * MainSearchPtr;          MainSearchFunc * MainSearchPtr;
         SearchData Data;  
   
         Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);  
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,  
                                 pParam->width, pParam->height, iFcode);  
1753    
1754          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1755          Data.iEdgedWidth = iEdgedWidth;          Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1756          Data.currentMV = currentMV;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1757          Data.iMinSAD = iMinSAD;                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
1758          Data.Ref = pRef + (x + iEdgedWidth*y)*16;  
1759          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
1760          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1761          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;          Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1762          Data.temp = temp;  
1763          Data.iQuant = iQuant;          Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16;
1764          Data.iFcode = iFcode;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
1765            Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
1766            Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
1767            Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1768            Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1769    
1770          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
1771                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
1772                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
1773                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
1774                  Data.max_dy = EVEN(Data.max_dy);                  Data->max_dy = EVEN(Data->max_dy);
1775          }          }
1776    
1777          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;          for(i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
1778    
1779          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
1780    
1781          if (inter4v)          if (inter4v || pParam->m_quarterpel || Data->chroma) CheckCandidate = CheckCandidate16;
                 CheckCandidate = CheckCandidate16;  
1782          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
1783    
   
1784          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);
1785          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);
1786          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
1787          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;
1788          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;
1789          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;
1790    
1791          CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);          (*CheckCandidate)(pMB->mvs[0].x, pMB->mvs[0].y, 0, &t, Data);
1792    
1793          if (pMB->mode == MODE_INTER4V)          if (pMB->mode == MODE_INTER4V)
1794                  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
1795                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);
1796                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);
1797                          if (!(make_mask(pMB->mvs, i)))                          if (!(make_mask(pMB->mvs, i)))
1798                                  CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);                                  (*CheckCandidate)(pMB->mvs[i].x, pMB->mvs[i].y, 0, &t, Data);
1799                  }                  }
1800    
1801          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1526  Line 1804 
1804                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1805                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1806    
1807          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1808    
1809          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1810    
1811          if (inter4v)          for(i = 0; i < 5; i++) {
1812                  for(i = 0; i < 4; i++)                  Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1813                          Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                  Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1814            }
1815    
1816            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1817                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1818                                    pParam->width, pParam->height, Data->iFcode, 0);
1819                    CheckCandidate = CheckCandidate16_qpel;
1820                    QuarterpelRefine(Data);
1821            }
1822    
1823            if (inter4v) {
1824                    SearchData Data8;
1825                    Data8.iFcode = Data->iFcode;
1826                    Data8.lambda8 = Data->lambda8;
1827                    Data8.iEdgedWidth = Data->iEdgedWidth;
1828                    Data8.RefQ = Data->RefQ;
1829                    Data8.qpel = Data->qpel;
1830                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1831                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1832                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1833                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1834    
1835                    if (Data->chroma) {
1836                            int sum, dx, dy;
1837    
1838                            if(pParam->m_quarterpel)
1839                                    sum = (pMB->qmvs[0].y + pMB->qmvs[1].y + pMB->qmvs[2].y + pMB->qmvs[3].y)/2;
1840                            else sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1841                            dy = (sum ? SIGN(sum) *
1842                                      (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2) : 0);
1843    
1844                            if(pParam->m_quarterpel)
1845                                    sum = (pMB->qmvs[0].x + pMB->qmvs[1].x + pMB->qmvs[2].x + pMB->qmvs[3].x)/2;
1846                            else sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1847                            dx = (sum ? SIGN(sum) *
1848                                      (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2) : 0);
1849                            Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);
1850                    }
1851            }
1852    
1853          if (!(inter4v) ||          if (!(inter4v) ||
1854                  (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] +
1855                                                            Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1856  // INTER MODE  // INTER MODE
   
1857                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1858                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1859                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1860    
1861                    pMB->qmvs[0] = pMB->qmvs[1]
1862                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1863    
1864                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1865                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1866    
1867                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1868                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predQMV.x;
1869                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predQMV.y;
1870                    } else {
1871                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1872                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1873                    }
1874          } else {          } else {
1875  // INTER4V MODE; all other things are already set in Search8hinted  // INTER4V MODE; all other things are already set in Search8
1876                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1877                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3]
1878                                                    + Data->iMinSAD[4] + IMV16X16 * iQuant;
1879          }          }
1880    
1881  }  }
# Line 1568  Line 1893 
1893          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
1894    
1895          uint32_t x, y;          uint32_t x, y;
1896            uint8_t * qimage;
1897            int32_t temp[5], quant = current->quant;
1898            int32_t iMinSAD[5];
1899            VECTOR currentMV[5], currentQMV[5];
1900            SearchData Data;
1901            Data.iEdgedWidth = pParam->edged_width;
1902            Data.currentMV = currentMV;
1903            Data.currentQMV = currentQMV;
1904            Data.iMinSAD = iMinSAD;
1905            Data.temp = temp;
1906            Data.iFcode = current->fcode;
1907            Data.rounding = pParam->m_rounding_type;
1908            Data.qpel = pParam->m_quarterpel;
1909            Data.chroma = current->global_flags & XVID_ME_COLOUR;
1910    
1911            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
1912                    return; // allocate some mem for qpel interpolated blocks
1913                                      // somehow this is dirty since I think we shouldn't use malloc outside
1914                                      // encoder_create() - so please fix me!
1915    
1916            Data.RefQ = qimage;
1917    
1918          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
1919    
1920          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
1921                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
                         int32_t sad00;  
1922    
1923                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
1924    
# Line 1583  Line 1928 
1928                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
1929                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
1930                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant; }
1931                            else {
1932                                    if (pMB->dquant != NO_CHANGE) {
1933                                            quant += DQtab[pMB->dquant];
1934                                            if (quant > 31) quant = 31;
1935                                            else if (quant < 1) quant = 1;
1936                                    }
1937                                    pMB->quant = quant;
1938                            }
1939    
1940                          if (pMB->dquant == NO_CHANGE) //no skip otherwise, anyway                          SearchPhinted(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
1941                                  sad00 = pMB->sad16                                                          y, current->motion_flags, pMB->quant,
1942                                          = sad16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
1943                                                                  pRef->y + (x + y * pParam->edged_width) * 16,                                                          &Data);
                                                                 pParam->edged_width, 256*4096 );  
                         else sad00 = 256*4096;  
1944    
1945                    }
1946            }
1947            free(qimage);
1948    }
1949    
1950  //initial skip decision  static __inline int
1951    MEanalyzeMB (   const uint8_t * const pRef,
1952                                    const uint8_t * const pCur,
1953                                    const int x,
1954                                    const int y,
1955                                    const MBParam * const pParam,
1956                                    const MACROBLOCK * const pMBs,
1957                                    MACROBLOCK * const pMB,
1958                                    SearchData * const Data)
1959    {
1960    
1961                          if ( (pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)          int i = 255, mask;
1962                                  && ( //(pMB->mode == MODE_NOT_CODED) ||          VECTOR pmv[3];
1963                                          (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant) )) ) {  
1964                                  if (sad00 < pMB->quant * INITIAL_SKIP_THRESH) {          *(Data->iMinSAD) = MV_MAX_ERROR;
1965                                          SkipMacroblockP(pMB, sad00);          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1966                                          continue; } //skipped          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1967                                    pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
1968    
1969            Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
1970            Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
1971    
1972            CheckCandidate = CheckCandidate16no4vI;
1973    
1974            pmv[1].x = EVEN(pMB->mvs[0].x);
1975            pmv[1].y = EVEN(pMB->mvs[0].y);
1976            pmv[0].x = EVEN(Data->predMV.x);
1977            pmv[0].y = EVEN(Data->predMV.y);
1978            pmv[2].x = pmv[2].y = 0;
1979    
1980            CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, Data);
1981            if (!(mask = make_mask(pmv, 1)))
1982                    CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, Data);
1983            if (!(mask = make_mask(pmv, 2)))
1984                    CheckCandidate16no4vI(0, 0, mask, &i, Data);
1985    
1986            DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
1987    
1988            pMB->mvs[0] = *Data->currentMV;
1989            pMB->mode = MODE_INTER;
1990    
1991            return *(Data->iMinSAD);
1992                          }                          }
                         else sad00 = 256*4096;  
1993    
1994                          if (pMB->mode == MODE_NOT_CODED)  #define INTRA_THRESH    1350
1995                                  SearchP(        pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,  #define INTER_THRESH    900
                                                         y, current->motion_flags, pMB->quant,  
                                                         current->fcode, pParam, pMBs, reference->mbs,  
                                                         current->global_flags & XVID_INTER4V, pMB);  
1996    
1997                          else  int
1998                                  SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,  MEanalysis(     const IMAGE * const pRef,
1999                                                          y, current->motion_flags, pMB->quant,                          const IMAGE * const pCurrent,
2000                                                          current->fcode, pParam, pMBs,                          MBParam * const pParam,
2001                                                          current->global_flags & XVID_INTER4V, pMB);                          MACROBLOCK * const pMBs,
2002                            const uint32_t iFcode)
2003    {
2004            uint32_t x, y, intra = 0;
2005            int sSAD = 0;
2006    
2007  /* final skip decision, a.k.a. "the vector you found, really that good?" */          VECTOR currentMV;
2008                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)          int32_t iMinSAD;
2009                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)          SearchData Data;
2010                                  SkipMacroblockP(pMB, sad00);          Data.iEdgedWidth = pParam->edged_width;
2011            Data.currentMV = &currentMV;
2012            Data.iMinSAD = &iMinSAD;
2013            Data.iFcode = iFcode;
2014    
2015            if (sadInit) (*sadInit) ();
2016    
2017            for (y = 1; y < pParam->mb_height-1; y++) {
2018                    for (x = 1; x < pParam->mb_width-1; x++) {
2019                            int sad, dev;
2020                            MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2021    
2022                            sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
2023                                                                    pParam, pMBs, pMB, &Data);
2024    
2025                            if (sad > INTRA_THRESH) {
2026                                    dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
2027                                                              pParam->edged_width);
2028                                    if (dev + INTRA_THRESH < sad) { intra++; pMB->mode = MODE_INTRA; }
2029                                    if (intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame
2030                                    }
2031                            sSAD += sad;
2032                  }                  }
2033          }          }
2034            sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2035            if (sSAD > INTER_THRESH ) return 1; //P frame
2036            emms();
2037            return 0; // B frame
2038    
2039  }  }
2040    
2041    int
2042    FindFcode(      const MBParam * const pParam,
2043                            const FRAMEINFO * const current)
2044    {
2045            uint32_t x, y;
2046            int max = 0, min = 0, i;
2047    
2048            for (y = 0; y < pParam->mb_height; y++) {
2049                    for (x = 0; x < pParam->mb_width; x++) {
2050    
2051                            MACROBLOCK *pMB = &current->mbs[x + y * pParam->mb_width];
2052                            for(i = 0; i < (pMB->mode == MODE_INTER4V ? 4:1); i++) {
2053                                    if (pMB->mvs[i].x > max) max = pMB->mvs[i].x;
2054                                    if (pMB->mvs[i].y > max) max = pMB->mvs[i].y;
2055    
2056                                    if (pMB->mvs[i].x < min) min = pMB->mvs[i].x;
2057                                    if (pMB->mvs[i].y < min) min = pMB->mvs[i].y;
2058                            }
2059                    }
2060            }
2061    
2062            min = -min;
2063            max += 1;
2064            if (min > max) max = min;
2065            if (pParam->m_quarterpel) max *= 2;
2066    
2067            for (i = 1; (max > 32 << (i - 1)); i++);
2068            return i;
2069    }
2070    
2071    static void
2072    CheckGMC(int x, int y, const int dir, int * iDirection,
2073                    const MACROBLOCK * const pMBs, uint32_t * bestcount, VECTOR * GMC,
2074                    const MBParam * const pParam)
2075    {
2076            uint32_t mx, my, a, count = 0;
2077    
2078            for (my = 1; my < pParam->mb_height-1; my++)
2079                    for (mx = 1; mx < pParam->mb_width-1; mx++) {
2080                            VECTOR mv;
2081                            const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2082                            if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED) continue;
2083                            mv = pMB->mvs[0];
2084                            a = ABS(mv.x - x) + ABS(mv.y - y);
2085                            if (a < 6) count += 6 - a;
2086                    }
2087    
2088            if (count > *bestcount) {
2089                    *bestcount = count;
2090                    *iDirection = dir;
2091                    GMC->x = x; GMC->y = y;
2092            }
2093    }
2094    
2095    
2096    static VECTOR
2097    GlobalMotionEst(const MACROBLOCK * const pMBs, const MBParam * const pParam, const uint32_t iFcode)
2098    {
2099    
2100            uint32_t count, bestcount = 0;
2101            int x, y;
2102            VECTOR gmc = {0,0};
2103            int step, min_x, max_x, min_y, max_y;
2104            uint32_t mx, my;
2105            int iDirection, bDirection;
2106    
2107            min_x = min_y = -32<<iFcode;
2108            max_x = max_y = 32<<iFcode;
2109    
2110    //step1: let's find a rough camera panning
2111            for (step = 32; step >= 2; step /= 2) {
2112                    bestcount = 0;
2113                    for (y = min_y; y <= max_y; y += step)
2114                            for (x = min_x ; x <= max_x; x += step) {
2115                                    count = 0;
2116                                    //for all macroblocks
2117                                    for (my = 1; my < pParam->mb_height-1; my++)
2118                                            for (mx = 1; mx < pParam->mb_width-1; mx++) {
2119                                                    const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2120                                                    VECTOR mv;
2121    
2122                                                    if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
2123                                                            continue;
2124    
2125                                                    mv = pMB->mvs[0];
2126                                                    if ( ABS(mv.x - x) <= step && ABS(mv.y - y) <= step )   /* GMC translation is always halfpel-res */
2127                                                            count++;
2128                                            }
2129                                    if (count >= bestcount) { bestcount = count; gmc.x = x; gmc.y = y; }
2130                            }
2131                    min_x = gmc.x - step;
2132                    max_x = gmc.x + step;
2133                    min_y = gmc.y - step;
2134                    max_y = gmc.y + step;
2135    
2136            }
2137    
2138            if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10)
2139                    gmc.x = gmc.y = 0; //no camara pan, no GMC
2140    
2141    // step2: let's refine camera panning using gradiend-descent approach.
2142    // TODO: more warping points may be evaluated here (like in interpolate mode search - two vectors in one diamond)
2143            bestcount = 0;
2144            CheckGMC(gmc.x, gmc.y, 255, &iDirection, pMBs, &bestcount, &gmc, pParam);
2145            do {
2146                    x = gmc.x; y = gmc.y;
2147                    bDirection = iDirection; iDirection = 0;
2148                    if (bDirection & 1) CheckGMC(x - 1, y, 1+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2149                    if (bDirection & 2) CheckGMC(x + 1, y, 2+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2150                    if (bDirection & 4) CheckGMC(x, y - 1, 1+2+4, &iDirection, pMBs, &bestcount, &gmc, pParam);
2151                    if (bDirection & 8) CheckGMC(x, y + 1, 1+2+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2152    
2153            } while (iDirection);
2154    
2155            if (pParam->m_quarterpel) {
2156                    gmc.x *= 2;
2157                    gmc.y *= 2;     /* we store the halfpel value as pseudo-qpel to make comparison easier */
2158            }
2159    
2160            return gmc;
2161    }

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

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