[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 628, Mon Nov 4 10:58:24 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 526  Line 756 
756          const IMAGE *const pCurrent = &current->image;          const IMAGE *const pCurrent = &current->image;
757          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
758    
759            FILE * debug;
760          const VECTOR zeroMV = { 0, 0 };          const VECTOR zeroMV = { 0, 0 };
761    
762          uint32_t x, y;          uint32_t x, y;
763          uint32_t iIntra = 0;          uint32_t iIntra = 0;
764          int32_t InterBias;          int32_t InterBias, quant = current->quant, sad00;
765            uint8_t *qimage;
766    
767            // some pre-initialized thingies for SearchP
768            int32_t temp[5];
769            VECTOR currentMV[5];
770            VECTOR currentQMV[5];
771            int32_t iMinSAD[5];
772            SearchData Data;
773            Data.iEdgedWidth = pParam->edged_width;
774            Data.currentMV = currentMV;
775            Data.currentQMV = currentQMV;
776            Data.iMinSAD = iMinSAD;
777            Data.temp = temp;
778            Data.iFcode = current->fcode;
779            Data.rounding = pParam->m_rounding_type;
780            Data.qpel = pParam->m_quarterpel;
781            Data.chroma = current->global_flags & XVID_ME_COLOUR;
782    
783            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
784                    return 1; // allocate some mem for qpel interpolated blocks
785                                      // somehow this is dirty since I think we shouldn't use malloc outside
786                                      // encoder_create() - so please fix me!
787            Data.RefQ = qimage;
788          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
789    
790          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
791                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
   
792                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
793                          int32_t sad00 =  pMB->sad16  
794                            pMB->sad16
795                                  = sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,                                  = sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,
796                                                          pRef->y + (x + y * pParam->edged_width) * 16,                                                          pRef->y + (x + y * pParam->edged_width) * 16,
797                                                          pParam->edged_width, pMB->sad8 );                                                          pParam->edged_width, pMB->sad8 );
798    
799                            if (Data.chroma) {
800                                    pMB->sad16 += sad8(pCurrent->u + x*8 + y*(pParam->edged_width/2)*8,
801                                                                    pRef->u + x*8 + y*(pParam->edged_width/2)*8, pParam->edged_width/2);
802    
803                                    pMB->sad16 += sad8(pCurrent->v + (x + y*(pParam->edged_width/2))*8,
804                                                                    pRef->v + (x + y*(pParam->edged_width/2))*8, pParam->edged_width/2);
805                            }
806    
807                            sad00 = pMB->sad16; //if no gmc; else sad00 = (..)
808    
809                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
810                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
811                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant;
812                            } else {
813                                    if (pMB->dquant != NO_CHANGE) {
814                                            quant += DQtab[pMB->dquant];
815                                            if (quant > 31) quant = 31;
816                                            else if (quant < 1) quant = 1;
817                                    }
818                                    pMB->quant = quant;
819                            }
820    
821  //initial skip decision  //initial skip decision
822    /* no early skip for GMC (global vector = skip vector is unknown!)  */
823                          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 */
824                                  && (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) ) {                                  if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * INITIAL_SKIP_THRESH)
825                                  if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {                                          if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
826                                                  SkipMacroblockP(pMB, sad00);                                                  SkipMacroblockP(pMB, sad00);
827                                                  continue;                                                  continue;
828                                  }                                  }
829                          } else sad00 = 256*4096; // skip not allowed - for final skip decision                          }
830    
831                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchP(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
832                                                  y, current->motion_flags, pMB->quant,                                                  y, current->motion_flags, pMB->quant,
833                                                  current->fcode, pParam, pMBs, reference->mbs,                                                  &Data, pParam, pMBs, reference->mbs,
834                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
835    
836  /* 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?" */
837                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)                          if (current->coding_type == P_VOP)      {
838                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)                                  if ( (pMB->dquant == NO_CHANGE) && (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)
839                                  { SkipMacroblockP(pMB, sad00); continue; }                                  && ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH) )
840                                            if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
841                                                    SkipMacroblockP(pMB, sad00);
842                                                    continue;
843                                            }
844                            }
845    
846  /* finally, intra decision */  /* finally, intra decision */
847    
848                          InterBias = MV16_INTER_BIAS;                          InterBias = MV16_INTER_BIAS;
849                          if (pMB->quant > 8)  InterBias += 50 * (pMB->quant - 8); // to make high quants work                          if (pMB->quant > 8)  InterBias += 80 * (pMB->quant - 8); // to make high quants work
850                          if (y != 0)                          if (y != 0)
851                                  if ((pMB - pParam->mb_width)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - pParam->mb_width)->mode == MODE_INTER ) InterBias -= 80;
852                          if (x != 0)                          if (x != 0)
853                                  if ((pMB - 1)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - 1)->mode == MODE_INTER ) InterBias -= 80;
854    
855                            if (Data.chroma) InterBias += 50; // to compensate bigger SAD
856    
857                          if (InterBias < pMB->sad16)  {                          if (InterBias < pMB->sad16)  {
858                                  const int32_t deviation =                                  const int32_t deviation =
# Line 582  Line 860 
860                                                    pParam->edged_width);                                                    pParam->edged_width);
861    
862                                  if (deviation < (pMB->sad16 - InterBias)) {                                  if (deviation < (pMB->sad16 - InterBias)) {
863                                          if (++iIntra >= iLimit) return 1;                                          if (++iIntra >= iLimit) { free(qimage); return 1; }
864                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
865                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
866                                                  pMB->mvs[3] = zeroMV;                                                  pMB->mvs[3] = zeroMV;
867                                            pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] =
868                                                            pMB->qmvs[3] = zeroMV;
869                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
870                                                  pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
871                                  }                                  }
872                          }                          }
873                  }                  }
874          }          }
875            free(qimage);
876    
877            if (current->coding_type == S_VOP)      /* first GMC step only for S(GMC)-VOPs */
878                    current->GMC_MV = GlobalMotionEst( pMBs, pParam, current->fcode );
879            else
880                    current->GMC_MV = zeroMV;
881    
882          return 0;          return 0;
883  }  }
884    
# Line 601  Line 888 
888  static __inline int  static __inline int
889  make_mask(const VECTOR * const pmv, const int i)  make_mask(const VECTOR * const pmv, const int i)
890  {  {
891          int mask = 0xFF, j;          int mask = 255, j;
892          for (j = 0; j < i; j++) {          for (j = 0; j < i; j++) {
893                  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
894                  if (pmv[i].x == pmv[j].x) {                  if (pmv[i].x == pmv[j].x) {
# Line 625  Line 912 
912    
913          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour
914                  pmv[5].x = EVEN(pmv[3].x);                  pmv[5].x = EVEN(pmv[3].x);
915                  pmv[5].y = EVEN(pmv[3].y); }                  pmv[5].y = EVEN(pmv[3].y);
916          else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
917    
918          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
919          else pmv[3].x = pmv[3].y = 0;          else pmv[3].x = pmv[3].y = 0;
# Line 644  Line 931 
931    
932          if ((x != iWcount-1) && (y != iHcount-1)) {          if ((x != iWcount-1) && (y != iHcount-1)) {
933                  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
934                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y); }                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
935          else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
936  }  }
937    
938  static void  static void
939  SearchP(const uint8_t * const pRef,  SearchP(const IMAGE * const pRef,
940                  const uint8_t * const pRefH,                  const uint8_t * const pRefH,
941                  const uint8_t * const pRefV,                  const uint8_t * const pRefV,
942                  const uint8_t * const pRefHV,                  const uint8_t * const pRefHV,
# Line 658  Line 945 
945                  const int y,                  const int y,
946                  const uint32_t MotionFlags,                  const uint32_t MotionFlags,
947                  const uint32_t iQuant,                  const uint32_t iQuant,
948                  const uint32_t iFcode,                  SearchData * const Data,
949                  const MBParam * const pParam,                  const MBParam * const pParam,
950                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
951                  const MACROBLOCK * const prevMBs,                  const MACROBLOCK * const prevMBs,
# Line 666  Line 953 
953                  MACROBLOCK * const pMB)                  MACROBLOCK * const pMB)
954  {  {
955    
         const int32_t iEdgedWidth = pParam->edged_width;  
   
956          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
957          int32_t temp[5];          VECTOR pmv[7];
         VECTOR currentMV[5], pmv[7];  
         int32_t psad[4], iMinSAD[5];  
         MainSearchFunc * MainSearchPtr;  
         SearchData Data;  
958    
959          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)()
960          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,
961                                  pParam->width, pParam->height, iFcode);                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
962    
963          Data.predMV = pmv[0];          Data->predMV = pmv[0];
964          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
965          Data.iEdgedWidth = iEdgedWidth;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
966          Data.currentMV = currentMV;          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8;
967          Data.iMinSAD = iMinSAD;          Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8;
968          Data.Ref = pRef + (x + iEdgedWidth*y)*16;  
969          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16;
970          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
971          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
972          Data.temp = temp;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
973            Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
974            Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
975    
976          Data.iQuant = iQuant;          Data->lambda16 = lambda_vec16[iQuant];
977          Data.iFcode = iFcode;          Data->lambda8 = lambda_vec8[iQuant];
978    
979          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
980                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
981                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
982                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
983                  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];  
984    
985          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
986    
987            for(i = 0;  i < 5; i++)
988                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
989    
990            if (pParam->m_quarterpel) {
991                    Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
992                    i = d_mv_bits(Data->predQMV.x, Data->predQMV.y, Data->iFcode);
993            } else i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);
994    
995            Data->iMinSAD[0] = pMB->sad16 + (Data->lambda16 * i * pMB->sad16)/1000;
996            Data->iMinSAD[1] = pMB->sad8[0] + (Data->lambda8 * i * (pMB->sad8[0]+NEIGH_8X8_BIAS))/100;
997            Data->iMinSAD[2] = pMB->sad8[1];
998            Data->iMinSAD[3] = pMB->sad8[2];
999            Data->iMinSAD[4] = pMB->sad8[3];
1000    
1001          if ((x == 0) && (y == 0)) threshA = 512;          if ((x == 0) && (y == 0)) threshA = 512;
1002          else {          else {
1003                  threshA = psad[0] + 20;                  threshA = Data->temp[0]; // that's when we keep this SAD atm
1004                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
1005                  if (threshA > 1024) threshA = 1024; }                  if (threshA > 1024) threshA = 1024; }
1006    
1007          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,
1008                                          prevMBs + x + y * pParam->mb_width);                                          prevMBs + x + y * pParam->mb_width);
1009    
1010          if (inter4v) CheckCandidate = CheckCandidate16;          if (inter4v || pParam->m_quarterpel || Data->chroma) CheckCandidate = CheckCandidate16;
1011          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
1012    
1013  /* main loop. checking all predictions */  /* main loop. checking all predictions */
1014    
1015          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
1016                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1017                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  (*CheckCandidate)(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1018                  if (iMinSAD[0] < threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1019          }          }
1020    
1021          if ((iMinSAD[0] <= threshA) ||          if ((Data->iMinSAD[0] <= threshA) ||
1022                          (MVequal(currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
1023                          (iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {                          (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {
1024                  inter4v = 0;                  inter4v = 0;
1025                  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;  
                 }  
         }  
1026    
1027          if (MotionFlags & PMV_USESQUARES16)                  MainSearchFunc * MainSearchPtr;
1028                  MainSearchPtr = SquareSearch;                  if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
1029          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
                 MainSearchPtr = AdvDiamondSearch;  
1030                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1031    
1032          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, iDirection);                  (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1033    
1034  /* extended search, diamond starting in 0,0 and in prediction.  /* extended search, diamond starting in 0,0 and in prediction.
1035          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 1037 
1037    
1038          if (MotionFlags & PMV_EXTSEARCH16) {          if (MotionFlags & PMV_EXTSEARCH16) {
1039                  int32_t bSAD;                  int32_t bSAD;
1040                  VECTOR startMV = Data.predMV, backupMV = currentMV[0];                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
1041                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?
1042                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);
1043                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1044                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1045    
1046                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1047                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1048                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1049                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1050                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1051                  }                  }
1052    
1053                  backupMV = currentMV[0];                          backupMV = Data->currentMV[0];
1054                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;
1055                  else startMV.x = startMV.y = 0;                  else startMV.x = startMV.y = 0;
1056                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1057                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1058    
1059                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1060                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1061                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1062                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1063                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1064                            }
1065                  }                  }
1066          }          }
1067    
1068  PMVfast16_Terminate_with_Refine:          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1069    
1070          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          for(i = 0; i < 5; i++) {
1071                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1072                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1073            }
1074    
1075            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1076    
1077  PMVfast16_Terminate_without_Refine:                  CheckCandidate = CheckCandidate16_qpel;
1078                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1079                                    pParam->width, pParam->height, Data->iFcode, 0);
1080    
1081          if (inter4v)                  QuarterpelRefine(Data);
1082                  for(i = 0; i < 4; i++)          }
1083                          Search8(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);  
1084            if (Data->iMinSAD[0] < (int32_t)iQuant * 30 ) inter4v = 0;
1085            if (inter4v) {
1086                    SearchData Data8;
1087                    Data8.iFcode = Data->iFcode;
1088                    Data8.lambda8 = Data->lambda8;
1089                    Data8.iEdgedWidth = Data->iEdgedWidth;
1090                    Data8.RefQ = Data->RefQ;
1091                    Data8.qpel = Data->qpel;
1092                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1093                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1094                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1095                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1096    
1097                    if (Data->chroma) {
1098                            int sum, dx, dy;
1099    
1100                            if(pParam->m_quarterpel) {
1101                                    sum = pMB->qmvs[0].y/2 + pMB->qmvs[1].y/2 + pMB->qmvs[2].y/2 + pMB->qmvs[3].y/2;
1102                            } else sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1103                            dy = (sum >> 3) + roundtab_76[sum & 0xf];
1104    
1105                            if(pParam->m_quarterpel) {
1106                                    sum = pMB->qmvs[0].x/2 + pMB->qmvs[1].x/2 + pMB->qmvs[2].x/2 + pMB->qmvs[3].x/2;
1107                            } else sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1108                            dx = (sum >> 3) + roundtab_76[sum & 0xf];
1109    
1110                            Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);
1111                    }
1112            }
1113    
1114          if (!(inter4v) ||          if (!(inter4v) ||
1115                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
1116                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1117  // INTER MODE  // INTER MODE
1118                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1119                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1120                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1121    
1122                    pMB->qmvs[0] = pMB->qmvs[1]
1123                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1124    
1125                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1126                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1127    
1128                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1129                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predQMV.x;
1130                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predQMV.y;
1131                    } else {
1132                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1133                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1134                    }
1135          } else {          } else {
1136  // INTER4V MODE; all other things are already set in Search8  // INTER4V MODE; all other things are already set in Search8
1137                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1138                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1139                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1140          }          }
   
1141  }  }
1142    
1143  static void  static void
# Line 820  Line 1147 
1147                  const MBParam * const pParam,                  const MBParam * const pParam,
1148                  MACROBLOCK * const pMB,                  MACROBLOCK * const pMB,
1149                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
1150                  const int block)                  const int block,
1151                    SearchData * const Data)
1152  {  {
1153          SearchData Data;          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1154            Data->currentMV = OldData->currentMV + 1 + block;
1155          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          Data->currentQMV = OldData->currentQMV + 1 + block;
1156          Data.iMinSAD = OldData->iMinSAD + 1 + block;  
1157          Data.currentMV = OldData->currentMV+1+block;          if(pParam->m_quarterpel) {
1158          Data.iFcode = OldData->iFcode;                  Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1159          Data.iQuant = OldData->iQuant;                  if (block != 0) *(Data->iMinSAD) += (Data->lambda8 *
1160                                                                            d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1161          if (block != 0)                                                                                                  Data->currentQMV->y - Data->predQMV.y,
1162                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *                                                                                                  Data->iFcode) * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
1163                                                                  d_mv_bits(      Data.currentMV->x - Data.predMV.x,          } else {
1164                                                                                          Data.currentMV->y - Data.predMV.y,                  Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1165                                                                                          Data.iFcode);                  if (block != 0) *(Data->iMinSAD) += (Data->lambda8 *
1166                                                                            d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1167                                                                                                    Data->currentMV->y - Data->predMV.y,
1168                                                                                                    Data->iFcode) * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
1169            }
1170    
1171          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
1172    
1173                  Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));
1174                  Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));
1175                  Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1176                  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));  
1177    
1178                  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);  
1179    
1180                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1181                                    pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1182                  CheckCandidate = CheckCandidate8;                  CheckCandidate = CheckCandidate8;
1183    
1184                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & PMV_EXTSEARCH8) {
1185                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1186    
1187                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1188                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1189                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1190                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1191    
1192                          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);     }                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1193    
1194                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                          if(*(Data->iMinSAD) < temp_sad) {
1195                                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1196                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1197          }          }
1198                    }
1199    
1200                    if (MotionFlags & PMV_HALFPELREFINE8) {
1201                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1202    
1203          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;                          HalfpelRefine(Data); // perform halfpel refine of current best vector
1204          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;  
1205          pMB->mvs[block] = *(Data.currentMV);                          if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1206          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                                  Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1207                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1208                            }
1209                    }
1210    
1211                    if(pParam->m_quarterpel) {
1212                            if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1213                                    (MotionFlags & PMV_QUARTERPELREFINE8)) {
1214                            CheckCandidate = CheckCandidate8_qpel;
1215                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1216                                    pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1217                            QuarterpelRefine(Data);
1218                            }
1219                    }
1220            }
1221    
1222            if(pParam->m_quarterpel) {
1223                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predQMV.x;
1224                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predQMV.y;
1225            }
1226            else {
1227                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1228                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1229            }
1230    
1231            pMB->mvs[block] = *(Data->currentMV);
1232            pMB->qmvs[block] = *(Data->currentQMV);
1233    
1234            pMB->sad8[block] =  4 * (*Data->iMinSAD);
1235  }  }
1236    
1237  /* B-frames code starts here */  /* B-frames code starts here */
# Line 896  Line 1259 
1259          pmv[2] = ChoosePred(pMB, mode_curr);          pmv[2] = ChoosePred(pMB, mode_curr);
1260          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);
1261    
         pmv[3].x = pmv[3].y = 0;  
1262          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour
1263                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);
1264                  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);
1265            } else pmv[3].x = pmv[3].y = 0;
1266    
1267          if (y != 0) {          if (y != 0) {
1268                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);
# Line 929  Line 1292 
1292                          const IMAGE * const pCur,                          const IMAGE * const pCur,
1293                          const int x, const int y,                          const int x, const int y,
1294                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
1295                          const uint32_t iFcode,                          const uint32_t iFcode,
1296                          const MBParam * const pParam,                          const MBParam * const pParam,
1297                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
1298                          const VECTOR * const predMV,                          const VECTOR * const predMV,
1299                          int32_t * const best_sad,                          int32_t * const best_sad,
1300                          const int32_t mode_current)                          const int32_t mode_current,
1301                            SearchData * const Data)
1302  {  {
1303    
1304          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1305    
1306          int i, iDirection, mask;          int i, iDirection, mask;
1307          VECTOR currentMV, pmv[7];          VECTOR pmv[7];
1308          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1309          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
1310          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;  
1311    
1312          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,          Data->Ref = pRef + (x + y * iEdgedWidth) * 16;
1313                                  pParam->width, pParam->height, iFcode);          Data->RefH = pRefH + (x + y * iEdgedWidth) * 16;
1314            Data->RefV = pRefV + (x + y * iEdgedWidth) * 16;
1315            Data->RefHV = pRefHV + (x + y * iEdgedWidth) * 16;
1316    
1317          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?  
1318    
1319            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1320                                    pParam->width, pParam->height, iFcode, pParam->m_quarterpel);
1321    
1322          pmv[0] = Data.predMV;          pmv[0] = Data->predMV;
1323          PreparePredictionsBF(pmv, x, y, pParam->mb_width,          PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
                                         pMB, mode_current);  
1324    
1325          currentMV.x = currentMV.y = 0;          Data->currentMV->x = Data->currentMV->y = 0;
1326    
1327          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1328    
1329  // main loop. checking all predictions  // main loop. checking all predictions
1330          for (i = 0; i < 8; i++) {          for (i = 0; i < 8; i++) {
1331                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1332                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1333          }          }
1334    
1335          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 990  Line 1338 
1338                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1339                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1340    
1341          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1342    
1343          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          HalfpelRefine(Data);
1344    
1345  // three bits are needed to code backward mode. four for forward  // three bits are needed to code backward mode. four for forward
1346  // we treat the bits just like they were vector's  // we treat the bits just like they were vector's
1347          if (mode_current == MODE_FORWARD) iMinSAD +=  4 * lambda_vec16[iQuant];          if (mode_current == MODE_FORWARD) *Data->iMinSAD +=  4 * Data->lambda16;
1348          else iMinSAD +=  3 * lambda_vec16[iQuant];          else *Data->iMinSAD +=  3 * Data->lambda16;
1349    
1350            if (*Data->iMinSAD < *best_sad) {
1351          if (iMinSAD < *best_sad) {                  *best_sad = *Data->iMinSAD;
                 *best_sad = iMinSAD;  
1352                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1353                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1354                  pMB->pmvs[0].y = currentMV.y - predMV->y;                  pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1355                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = *(Data->currentMV+2) = *Data->currentMV;
1356                  else pMB->b_mvs[0] = currentMV;                  else pMB->b_mvs[0] = *(Data->currentMV+1) = *Data->currentMV; //we store currmv for interpolate search
1357          }          }
1358    
1359  }  }
1360    
1361  static int32_t  static int32_t
1362  SearchDirect(const uint8_t * const f_Ref,  SearchDirect(const IMAGE * const f_Ref,
1363                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1364                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
1365                                  const uint8_t * const f_RefHV,                                  const uint8_t * const f_RefHV,
1366                                  const uint8_t * const b_Ref,                                  const IMAGE * const b_Ref,
1367                                  const uint8_t * const b_RefH,                                  const uint8_t * const b_RefH,
1368                                  const uint8_t * const b_RefV,                                  const uint8_t * const b_RefV,
1369                                  const uint8_t * const b_RefHV,                                  const uint8_t * const b_RefHV,
1370                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1371                                  const int x, const int y,                                  const int x, const int y,
1372                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1373                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1374                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1375                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1376                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1377                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1378                                    SearchData * const Data)
1379    
1380  {  {
1381          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
         int32_t iMinSAD = 0, skip_sad;  
1382          int k;          int k;
1383          VECTOR currentMV;  
1384          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
         SearchData Data;  
1385    
1386          Data.iMinSAD = &iMinSAD;          *Data->iMinSAD = 256*4096;
1387          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;  
1388    
1389          Data.Ref= f_Ref + (x + iEdgedWidth*y) * 16;          Data->Ref = f_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1390          Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;          Data->RefH = f_RefH + (x + Data->iEdgedWidth*y) * 16;
1391          Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;          Data->RefV = f_RefV + (x + Data->iEdgedWidth*y) * 16;
1392          Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = f_RefHV + (x + Data->iEdgedWidth*y) * 16;
1393          Data.bRef = b_Ref + (x + iEdgedWidth*y) * 16;          Data->bRef = b_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1394          Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;          Data->bRefH = b_RefH + (x + Data->iEdgedWidth*y) * 16;
1395          Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;          Data->bRefV = b_RefV + (x + Data->iEdgedWidth*y) * 16;
1396          Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;          Data->bRefHV = b_RefHV + (x + Data->iEdgedWidth*y) * 16;
1397  /*  
1398  //What we do here is a complicated version of CheckCandidateDirect(0,0);          Data->max_dx = 2 * pParam->width - 2 * (x) * 16;
1399  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;
1400            Data->min_dx = -(2 * 16 + 2 * (x) * 16);
1401  */          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);  
1402    
1403          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1404                  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);
1405                  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;
1406                  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);
1407                  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; }  
1408    
1409                    if ( ( pMB->b_mvs[k].x > Data->max_dx ) || ( pMB->b_mvs[k].x < Data->min_dx )
1410                            || ( pMB->b_mvs[k].y > Data->max_dy ) || ( pMB->b_mvs[k].y < Data->min_dy )) {
1411    
1412                            *best_sad = 256*4096; // in that case, we won't use direct mode
1413                            pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
1414                            pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;
1415                            return 0;
1416                    }
1417          if (b_mb->mode != MODE_INTER4V) {          if (b_mb->mode != MODE_INTER4V) {
1418                  iMinSAD = sad16bi(Data.Cur,                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1419                                                  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];
1420                                                                  x, y, 16, &pMB->mvs[0], iEdgedWidth),                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1421                                                  get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1422                                                                  x, y, 16, &pMB->b_mvs[0], iEdgedWidth), iEdgedWidth);                          break;
1423                    }
                 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);  
1424          }          }
1425    
 // 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;  
1426          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1427                  CheckCandidate = CheckCandidateDirect;                  CheckCandidate = CheckCandidateDirect;
1428          else CheckCandidate = CheckCandidateDirectno4v;          else CheckCandidate = CheckCandidateDirectno4v;
1429    
1430            (*CheckCandidate)(0, 0, 255, &k, Data);
1431    
1432    // skip decision
1433            if (*Data->iMinSAD < pMB->quant * SKIP_THRESH_B) {
1434                    //possible skip - checking chroma. everything copied from MC
1435                    //this is not full chroma compensation, only it's fullpel approximation. should work though
1436                    int sum, dx, dy, b_dx, b_dy;
1437    
1438                    sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1439                    dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1440    
1441                    sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1442                    dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1443    
1444                    sum = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;
1445                    b_dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1446    
1447                    sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;
1448                    b_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1449    
1450                    sum = sad8bi(pCur->u + 8*x + 8*y*(Data->iEdgedWidth/2),
1451                                            f_Ref->u + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1452                                            b_Ref->u + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1453                                            Data->iEdgedWidth/2);
1454                    sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1455                                            f_Ref->v + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1456                                            b_Ref->v + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1457                                            Data->iEdgedWidth/2);
1458    
1459                    if (sum < MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) {
1460                            pMB->mode = MODE_DIRECT_NONE_MV;
1461                            return *Data->iMinSAD;
1462                    }
1463            }
1464    
1465            skip_sad = *Data->iMinSAD;
1466    
1467  //  DIRECT MODE DELTA VECTOR SEARCH.  //  DIRECT MODE DELTA VECTOR SEARCH.
1468  //      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
1469    
# Line 1123  Line 1471 
1471                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1472                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1473    
1474          (*MainSearchPtr)(0, 0, &Data, 255);          (*MainSearchPtr)(0, 0, Data, 255);
1475    
1476          HalfpelRefine(&Data);          HalfpelRefine(Data);
1477    
1478          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
1479          *best_sad = iMinSAD;          *best_sad = *Data->iMinSAD;
1480    
1481          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1482                  pMB->mode = MODE_DIRECT;                  pMB->mode = MODE_DIRECT;
1483          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1484    
1485          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1486    
1487          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1488                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1489                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = ((Data->currentMV->x == 0)
1490                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1491                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          : pMB->mvs[k].x - Data->referencemv[k].x);
1492                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1493                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1494                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1495                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1496                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1497                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1498                          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];
1499                          break;                          break;
1500                  }                  }
1501          }          }
1502          return 0;//skip_sad;          return skip_sad;
1503  }  }
1504    
1505    
1506  static __inline void  static __inline void
1507  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const uint8_t * const f_Ref,
1508                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
# Line 1168  Line 1517 
1517                                  const uint32_t fcode,                                  const uint32_t fcode,
1518                                  const uint32_t bcode,                                  const uint32_t bcode,
1519                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1520                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1521                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1522                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1523                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1524                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1525                                    SearchData * const fData)
1526    
1527  {  {
 /* 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". */  
1528    
1529          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1530    
1531          int iDirection, i, j;          int iDirection, i, j;
1532          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;  
1533    
1534          bData.bpredMV = fData.predMV = *f_predMV;          *(bData.iMinSAD = fData->iMinSAD) = 4096*256;
1535          fData.bpredMV = bData.predMV = *b_predMV;          bData.Cur = fData->Cur;
1536            fData->iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;
1537            bData.currentMV = fData->currentMV + 1;
1538            bData.lambda16 = fData->lambda16;
1539            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1540    
1541            bData.bRef = fData->Ref = f_Ref + (x + y * iEdgedWidth) * 16;
1542            bData.bRefH = fData->RefH = f_RefH + (x + y * iEdgedWidth) * 16;
1543            bData.bRefV = fData->RefV = f_RefV + (x + y * iEdgedWidth) * 16;
1544            bData.bRefHV = fData->RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;
1545            bData.Ref = fData->bRef = b_Ref + (x + y * iEdgedWidth) * 16;
1546            bData.RefH = fData->bRefH = b_RefH + (x + y * iEdgedWidth) * 16;
1547            bData.RefV = fData->bRefV = b_RefV + (x + y * iEdgedWidth) * 16;
1548            bData.RefHV = fData->bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;
1549    
1550            bData.bpredMV = fData->predMV = *f_predMV;
1551            fData->bpredMV = bData.predMV = *b_predMV;
1552    
1553            fData->currentMV[0] = fData->currentMV[3]; //forward search stored it's vector here. backward stored it in the place it's needed
1554            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);
1555            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);
1556    
1557            if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1558            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dy;
1559            if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dx;
1560            if (fData->currentMV[0].y > fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1561    
1562            if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1563            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dy;
1564            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dx;
1565            if (fData->currentMV[1].y > bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1566    
1567            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);  
1568    
1569  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)
1570    
1571          do {          do {
1572                  iDirection = 255;                  iDirection = 255;
1573                  // forward MV moves                  // forward MV moves
1574                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
1575    
1576                  CheckCandidateInt(i + 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1577                  CheckCandidateInt(i, j + 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1578                  CheckCandidateInt(i - 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1579                  CheckCandidateInt(i, j - 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
1580    
1581                  // backward MV moves                  // backward MV moves
1582                  i = currentMV[1].x; j = currentMV[1].y;                  i = fData->currentMV[1].x; j = fData->currentMV[1].y;
1583                  currentMV[2] = currentMV[0];                  fData->currentMV[2] = fData->currentMV[0];
1584    
1585                  CheckCandidateInt(i + 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1586                  CheckCandidateInt(i, j + 2, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1587                  CheckCandidateInt(i - 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
1588                  CheckCandidateInt(i, j - 2, 0, &iDirection, &bData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, &bData);
1589    
1590          } while (!(iDirection));          } while (!(iDirection));
1591    
1592  /* 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);  
         }  
1593    
1594  // two bits are needed to code interpolate mode. we treat the bits just like they were vector's          if (*fData->iMinSAD < *best_sad) {
1595          iMinSAD +=  2 * lambda_vec16[iQuant];                  *best_sad = *fData->iMinSAD;
1596          if (iMinSAD < *best_sad) {                  pMB->mvs[0] = fData->currentMV[0];
1597                  *best_sad = iMinSAD;                  pMB->b_mvs[0] = fData->currentMV[1];
                 pMB->mvs[0] = currentMV[0];  
                 pMB->b_mvs[0] = currentMV[1];  
1598                  pMB->mode = MODE_INTERPOLATE;                  pMB->mode = MODE_INTERPOLATE;
1599    
1600                  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 1632 
1632          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1633          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
1634    
1635    // some pre-inintialized data for the rest of the search
1636    
1637            SearchData Data;
1638            int32_t iMinSAD;
1639            VECTOR currentMV[3];
1640            Data.iEdgedWidth = pParam->edged_width;
1641            Data.currentMV = currentMV;
1642            Data.iMinSAD = &iMinSAD;
1643            Data.lambda16 = lambda_vec16[frame->quant];
1644    
1645          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
1646    
1647          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
# Line 1303  Line 1652 
1652                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;
1653                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;
1654    
1655  /* special case, if collocated block is SKIPed: encoding is forward (0,0), cpb=0 without further ado */  /* special case, if collocated block is SKIPed in P-VOP: encoding is forward (0,0), cpb=0 without further ado */
1656                          if (b_mb->mode == MODE_NOT_CODED) {                          if (b_mb->mode == MODE_NOT_CODED) {
1657                                  pMB->mode = MODE_NOT_CODED;                                  pMB->mode = MODE_NOT_CODED;
1658                                  continue;                                  continue;
1659                          }                          }
1660    
1661                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
1662                            pMB->quant = frame->quant;
1663    
1664  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
1665          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
1666                            skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
1667                          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,  
1668                                                                          &frame->image,                                                                          &frame->image,
1669                                                                          i, j,                                                                          i, j,
1670                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
1671                                                                          TRB, TRD,                                                                          TRB, TRD,
1672                                                                          pParam,                                                                          pParam,
1673                                                                          pMB, b_mb,                                                                          pMB, b_mb,
1674                                                                          &best_sad);                                                                          &best_sad,
1675                                                                            &Data);
1676    
                         if (!(frame->global_flags & XVID_HALFPEL)) best_sad = skip_sad = 256*4096;  
                         else  
1677                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1678    
 //                      best_sad = 256*4096; //uncomment to disable Directsearch.  
 //      To disable any other mode, just comment the function call  
   
1679                          // forward search                          // forward search
1680                          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,
1681                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1682                                                  frame->motion_flags,                                                  frame->motion_flags,
1683                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
1684                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
1685                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
1686    
1687                          // backward search                          // backward search
1688                          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,
1689                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1690                                                  frame->motion_flags,                                                  frame->motion_flags,
1691                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
1692                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
1693                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
1694    
1695                          // 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
1696    
# Line 1354  Line 1700 
1700                                                  i, j,                                                  i, j,
1701                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
1702                                                  frame->motion_flags,                                                  frame->motion_flags,
1703                                                  frame->quant, pParam,                                                  pParam,
1704                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
1705                                                  pMB, &best_sad);                                                  pMB, &best_sad,
1706                                                    &Data);
1707    
1708                          switch (pMB->mode) {                          switch (pMB->mode) {
1709                                  case MODE_FORWARD:                                  case MODE_FORWARD:
# Line 1381  Line 1728 
1728                          }                          }
1729                  }                  }
1730          }          }
   
 //      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);  
   
1731  }  }
1732    
1733  /* Hinted ME starts here */  /* Hinted ME starts here */
1734    
 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));  
 }  
   
   
1735  static void  static void
1736  SearchPhinted ( const uint8_t * const pRef,  SearchPhinted ( const IMAGE * const pRef,
1737                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
1738                                  const uint8_t * const pRefV,                                  const uint8_t * const pRefV,
1739                                  const uint8_t * const pRefHV,                                  const uint8_t * const pRefHV,
# Line 1455  Line 1742 
1742                                  const int y,                                  const int y,
1743                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1744                                  const uint32_t iQuant,                                  const uint32_t iQuant,
                                 const uint32_t iFcode,  
1745                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1746                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1747                                  int inter4v,                                  int inter4v,
1748                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
1749                                    SearchData * const Data)
1750  {  {
1751    
1752          const int32_t iEdgedWidth = pParam->edged_width;          int i, t;
   
         int i;  
         VECTOR currentMV[5];  
         int32_t iMinSAD[5];  
         int32_t temp[5];  
1753          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);  
1754    
1755          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1756          Data.iEdgedWidth = iEdgedWidth;          Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1757          Data.currentMV = currentMV;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1758          Data.iMinSAD = iMinSAD;                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
1759          Data.Ref = pRef + (x + iEdgedWidth*y)*16;  
1760          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
1761          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1762          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;          Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1763          Data.temp = temp;  
1764          Data.iQuant = iQuant;          Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16;
1765          Data.iFcode = iFcode;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
1766            Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
1767            Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
1768            Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1769            Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1770    
1771          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
1772                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
1773                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
1774                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
1775                  Data.max_dy = EVEN(Data.max_dy);                  Data->max_dy = EVEN(Data->max_dy);
1776          }          }
1777    
1778          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;          for(i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
1779    
1780          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
1781    
1782          if (inter4v)          if (inter4v || pParam->m_quarterpel || Data->chroma) CheckCandidate = CheckCandidate16;
                 CheckCandidate = CheckCandidate16;  
1783          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
1784    
   
1785          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);
1786          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);
1787          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
1788          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;
1789          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;
1790          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;
1791    
1792          CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);          (*CheckCandidate)(pMB->mvs[0].x, pMB->mvs[0].y, 0, &t, Data);
1793    
1794          if (pMB->mode == MODE_INTER4V)          if (pMB->mode == MODE_INTER4V)
1795                  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
1796                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);
1797                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);
1798                          if (!(make_mask(pMB->mvs, i)))                          if (!(make_mask(pMB->mvs, i)))
1799                                  CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);                                  (*CheckCandidate)(pMB->mvs[i].x, pMB->mvs[i].y, 0, &t, Data);
1800                  }                  }
1801    
1802          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1526  Line 1805 
1805                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1806                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1807    
1808          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1809    
1810          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1811    
1812          if (inter4v)          for(i = 0; i < 5; i++) {
1813                  for(i = 0; i < 4; i++)                  Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1814                          Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                  Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1815            }
1816    
1817            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1818                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1819                                    pParam->width, pParam->height, Data->iFcode, 0);
1820                    CheckCandidate = CheckCandidate16_qpel;
1821                    QuarterpelRefine(Data);
1822            }
1823    
1824            if (inter4v) {
1825                    SearchData Data8;
1826                    Data8.iFcode = Data->iFcode;
1827                    Data8.lambda8 = Data->lambda8;
1828                    Data8.iEdgedWidth = Data->iEdgedWidth;
1829                    Data8.RefQ = Data->RefQ;
1830                    Data8.qpel = Data->qpel;
1831                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1832                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1833                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1834                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1835    
1836                    if (Data->chroma) {
1837                            int sum, dx, dy;
1838    
1839                            if(pParam->m_quarterpel)
1840                                    sum = (pMB->qmvs[0].y + pMB->qmvs[1].y + pMB->qmvs[2].y + pMB->qmvs[3].y)/2;
1841                            else sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1842                            dy = (sum ? SIGN(sum) *
1843                                      (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2) : 0);
1844    
1845                            if(pParam->m_quarterpel)
1846                                    sum = (pMB->qmvs[0].x + pMB->qmvs[1].x + pMB->qmvs[2].x + pMB->qmvs[3].x)/2;
1847                            else sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1848                            dx = (sum ? SIGN(sum) *
1849                                      (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2) : 0);
1850                            Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);
1851                    }
1852            }
1853    
1854          if (!(inter4v) ||          if (!(inter4v) ||
1855                  (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] +
1856                                                            Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1857  // INTER MODE  // INTER MODE
   
1858                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1859                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1860                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1861    
1862                    pMB->qmvs[0] = pMB->qmvs[1]
1863                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1864    
1865                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1866                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1867    
1868                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1869                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predQMV.x;
1870                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predQMV.y;
1871                    } else {
1872                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1873                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1874                    }
1875          } else {          } else {
1876  // INTER4V MODE; all other things are already set in Search8hinted  // INTER4V MODE; all other things are already set in Search8
1877                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1878                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3]
1879                                                    + Data->iMinSAD[4] + IMV16X16 * iQuant;
1880          }          }
1881    
1882  }  }
# Line 1568  Line 1894 
1894          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
1895    
1896          uint32_t x, y;          uint32_t x, y;
1897            uint8_t * qimage;
1898            int32_t temp[5], quant = current->quant;
1899            int32_t iMinSAD[5];
1900            VECTOR currentMV[5], currentQMV[5];
1901            SearchData Data;
1902            Data.iEdgedWidth = pParam->edged_width;
1903            Data.currentMV = currentMV;
1904            Data.currentQMV = currentQMV;
1905            Data.iMinSAD = iMinSAD;
1906            Data.temp = temp;
1907            Data.iFcode = current->fcode;
1908            Data.rounding = pParam->m_rounding_type;
1909            Data.qpel = pParam->m_quarterpel;
1910            Data.chroma = current->global_flags & XVID_ME_COLOUR;
1911    
1912            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
1913                    return; // allocate some mem for qpel interpolated blocks
1914                                      // somehow this is dirty since I think we shouldn't use malloc outside
1915                                      // encoder_create() - so please fix me!
1916    
1917            Data.RefQ = qimage;
1918    
1919          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
1920    
1921          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
1922                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
                         int32_t sad00;  
1923    
1924                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
1925    
# Line 1583  Line 1929 
1929                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
1930                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
1931                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant; }
1932                            else {
1933                                    if (pMB->dquant != NO_CHANGE) {
1934                                            quant += DQtab[pMB->dquant];
1935                                            if (quant > 31) quant = 31;
1936                                            else if (quant < 1) quant = 1;
1937                                    }
1938                                    pMB->quant = quant;
1939                            }
1940    
1941                          if (pMB->dquant == NO_CHANGE) //no skip otherwise, anyway                          SearchPhinted(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
1942                                  sad00 = pMB->sad16                                                          y, current->motion_flags, pMB->quant,
1943                                          = sad16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
1944                                                                  pRef->y + (x + y * pParam->edged_width) * 16,                                                          &Data);
                                                                 pParam->edged_width, 256*4096 );  
                         else sad00 = 256*4096;  
1945    
1946                    }
1947            }
1948            free(qimage);
1949    }
1950    
1951  //initial skip decision  static __inline int
1952    MEanalyzeMB (   const uint8_t * const pRef,
1953                                    const uint8_t * const pCur,
1954                                    const int x,
1955                                    const int y,
1956                                    const MBParam * const pParam,
1957                                    const MACROBLOCK * const pMBs,
1958                                    MACROBLOCK * const pMB,
1959                                    SearchData * const Data)
1960    {
1961    
1962                          if ( (pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)          int i = 255, mask;
1963                                  && ( //(pMB->mode == MODE_NOT_CODED) ||          VECTOR pmv[3];
1964                                          (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant) )) ) {  
1965                                  if (sad00 < pMB->quant * INITIAL_SKIP_THRESH) {          *(Data->iMinSAD) = MV_MAX_ERROR;
1966                                          SkipMacroblockP(pMB, sad00);          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1967                                          continue; } //skipped          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1968                                    pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
1969    
1970            Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
1971            Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
1972    
1973            CheckCandidate = CheckCandidate16no4vI;
1974    
1975            pmv[1].x = EVEN(pMB->mvs[0].x);
1976            pmv[1].y = EVEN(pMB->mvs[0].y);
1977            pmv[0].x = EVEN(Data->predMV.x);
1978            pmv[0].y = EVEN(Data->predMV.y);
1979            pmv[2].x = pmv[2].y = 0;
1980    
1981            CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, Data);
1982            if (!(mask = make_mask(pmv, 1)))
1983                    CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, Data);
1984            if (!(mask = make_mask(pmv, 2)))
1985                    CheckCandidate16no4vI(0, 0, mask, &i, Data);
1986    
1987            DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
1988    
1989            pMB->mvs[0] = *Data->currentMV;
1990            pMB->mode = MODE_INTER;
1991    
1992            return *(Data->iMinSAD);
1993                          }                          }
                         else sad00 = 256*4096;  
1994    
1995                          if (pMB->mode == MODE_NOT_CODED)  #define INTRA_THRESH    1350
1996                                  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);  
1997    
1998                          else  int
1999                                  SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,  MEanalysis(     const IMAGE * const pRef,
2000                                                          y, current->motion_flags, pMB->quant,                          const IMAGE * const pCurrent,
2001                                                          current->fcode, pParam, pMBs,                          MBParam * const pParam,
2002                                                          current->global_flags & XVID_INTER4V, pMB);                          MACROBLOCK * const pMBs,
2003                            const uint32_t iFcode)
2004    {
2005            uint32_t x, y, intra = 0;
2006            int sSAD = 0;
2007    
2008  /* final skip decision, a.k.a. "the vector you found, really that good?" */          VECTOR currentMV;
2009                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)          int32_t iMinSAD;
2010                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)          SearchData Data;
2011                                  SkipMacroblockP(pMB, sad00);          Data.iEdgedWidth = pParam->edged_width;
2012            Data.currentMV = &currentMV;
2013            Data.iMinSAD = &iMinSAD;
2014            Data.iFcode = iFcode;
2015    
2016            if (sadInit) (*sadInit) ();
2017    
2018            for (y = 1; y < pParam->mb_height-1; y++) {
2019                    for (x = 1; x < pParam->mb_width-1; x++) {
2020                            int sad, dev;
2021                            MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2022    
2023                            sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
2024                                                                    pParam, pMBs, pMB, &Data);
2025    
2026                            if (sad > INTRA_THRESH) {
2027                                    dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
2028                                                              pParam->edged_width);
2029                                    if (dev + INTRA_THRESH < sad) { intra++; pMB->mode = MODE_INTRA; }
2030                                    if (intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame
2031                                    }
2032                            sSAD += sad;
2033                  }                  }
2034          }          }
2035            sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2036            if (sSAD > INTER_THRESH ) return 1; //P frame
2037            emms();
2038            return 0; // B frame
2039    
2040  }  }
2041    
2042    int
2043    FindFcode(      const MBParam * const pParam,
2044                            const FRAMEINFO * const current)
2045    {
2046            uint32_t x, y;
2047            int max = 0, min = 0, i;
2048    
2049            for (y = 0; y < pParam->mb_height; y++) {
2050                    for (x = 0; x < pParam->mb_width; x++) {
2051    
2052                            MACROBLOCK *pMB = &current->mbs[x + y * pParam->mb_width];
2053                            for(i = 0; i < (pMB->mode == MODE_INTER4V ? 4:1); i++) {
2054                                    if (pMB->mvs[i].x > max) max = pMB->mvs[i].x;
2055                                    if (pMB->mvs[i].y > max) max = pMB->mvs[i].y;
2056    
2057                                    if (pMB->mvs[i].x < min) min = pMB->mvs[i].x;
2058                                    if (pMB->mvs[i].y < min) min = pMB->mvs[i].y;
2059                            }
2060                    }
2061            }
2062    
2063            min = -min;
2064            max += 1;
2065            if (min > max) max = min;
2066            if (pParam->m_quarterpel) max *= 2;
2067    
2068            for (i = 1; (max > 32 << (i - 1)); i++);
2069            return i;
2070    }
2071    
2072    static void
2073    CheckGMC(int x, int y, const int dir, int * iDirection,
2074                    const MACROBLOCK * const pMBs, uint32_t * bestcount, VECTOR * GMC,
2075                    const MBParam * const pParam)
2076    {
2077            uint32_t mx, my, a, count = 0;
2078    
2079            for (my = 1; my < pParam->mb_height-1; my++)
2080                    for (mx = 1; mx < pParam->mb_width-1; mx++) {
2081                            VECTOR mv;
2082                            const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2083                            if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED) continue;
2084                            mv = pMB->mvs[0];
2085                            a = ABS(mv.x - x) + ABS(mv.y - y);
2086                            if (a < 6) count += 6 - a;
2087                    }
2088    
2089            if (count > *bestcount) {
2090                    *bestcount = count;
2091                    *iDirection = dir;
2092                    GMC->x = x; GMC->y = y;
2093            }
2094    }
2095    
2096    
2097    static VECTOR
2098    GlobalMotionEst(const MACROBLOCK * const pMBs, const MBParam * const pParam, const uint32_t iFcode)
2099    {
2100    
2101            uint32_t count, bestcount = 0;
2102            int x, y;
2103            VECTOR gmc = {0,0};
2104            int step, min_x, max_x, min_y, max_y;
2105            uint32_t mx, my;
2106            int iDirection, bDirection;
2107    
2108            min_x = min_y = -32<<iFcode;
2109            max_x = max_y = 32<<iFcode;
2110    
2111    //step1: let's find a rough camera panning
2112            for (step = 32; step >= 2; step /= 2) {
2113                    bestcount = 0;
2114                    for (y = min_y; y <= max_y; y += step)
2115                            for (x = min_x ; x <= max_x; x += step) {
2116                                    count = 0;
2117                                    //for all macroblocks
2118                                    for (my = 1; my < pParam->mb_height-1; my++)
2119                                            for (mx = 1; mx < pParam->mb_width-1; mx++) {
2120                                                    const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2121                                                    VECTOR mv;
2122    
2123                                                    if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
2124                                                            continue;
2125    
2126                                                    mv = pMB->mvs[0];
2127                                                    if ( ABS(mv.x - x) <= step && ABS(mv.y - y) <= step )   /* GMC translation is always halfpel-res */
2128                                                            count++;
2129                                            }
2130                                    if (count >= bestcount) { bestcount = count; gmc.x = x; gmc.y = y; }
2131                            }
2132                    min_x = gmc.x - step;
2133                    max_x = gmc.x + step;
2134                    min_y = gmc.y - step;
2135                    max_y = gmc.y + step;
2136    
2137            }
2138    
2139            if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10)
2140                    gmc.x = gmc.y = 0; //no camara pan, no GMC
2141    
2142    // step2: let's refine camera panning using gradiend-descent approach.
2143    // TODO: more warping points may be evaluated here (like in interpolate mode search - two vectors in one diamond)
2144            bestcount = 0;
2145            CheckGMC(gmc.x, gmc.y, 255, &iDirection, pMBs, &bestcount, &gmc, pParam);
2146            do {
2147                    x = gmc.x; y = gmc.y;
2148                    bDirection = iDirection; iDirection = 0;
2149                    if (bDirection & 1) CheckGMC(x - 1, y, 1+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2150                    if (bDirection & 2) CheckGMC(x + 1, y, 2+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2151                    if (bDirection & 4) CheckGMC(x, y - 1, 1+2+4, &iDirection, pMBs, &bestcount, &gmc, pParam);
2152                    if (bDirection & 8) CheckGMC(x, y + 1, 1+2+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2153    
2154            } while (iDirection);
2155    
2156            if (pParam->m_quarterpel) {
2157                    gmc.x *= 2;
2158                    gmc.y *= 2;     /* we store the halfpel value as pseudo-qpel to make comparison easier */
2159            }
2160    
2161            return gmc;
2162    }

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

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