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

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

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

revision 539, Wed Sep 25 21:28:48 2002 UTC revision 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"
# Line 51  Line 52 
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 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  #define iDiamondSize 2  #define iDiamondSize 2
66    
67  static __inline int  static __inline int
# Line 78  Line 89 
89          return xb + yb;          return xb + yb;
90  }  }
91    
92    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 */  /* 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;  
136          int t;          int t;
137          const uint8_t * Reference;          const uint8_t * Reference;
138    
# Line 98  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          t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          if (data->qpel) t = d_mv_bits(2*x - data->predQMV.x, 2*y - data->predQMV.y, data->iFcode);
152          data->temp[0] += lambda_vec16[data->iQuant] * t;          else t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
153          data->temp[1] += lambda_vec8[data->iQuant] * t;  
154            data->temp[0] += (data->lambda16 * t * data->temp[0])/1000;
155            data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))/100;
156    
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 137  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 148  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)  CheckCandidate16no4vI(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
281  {  {
282          int32_t sad;          int32_t sad;
# Line 155  Line 284 
284          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
285                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
286    
287          sad = lambda_vec16[data->iQuant] *          sad = sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),
                         d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);  
   
         sad += sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),  
288                                          data->iEdgedWidth, 256*4096);                                          data->iEdgedWidth, 256*4096);
289    
290          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
# Line 193  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 208  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 216  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 255  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 269  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 302  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 313  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 328  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 336  Line 464 
464                  *dir = Direction; }                  *dir = Direction; }
465  }  }
466    
467    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 */  /* CHECK_CANDIATE FUNCTIONS END */
524    
525  /* MAINSEARCH FUNCTIONS START */  /* MAINSEARCH FUNCTIONS START */
# Line 504  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 517  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 530  Line 736 
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 = 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 = 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 546  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          // some pre-initialized thingies for SearchP
768          int32_t temp[5];          int32_t temp[5];
769          VECTOR currentMV[5];          VECTOR currentMV[5];
770            VECTOR currentQMV[5];
771          int32_t iMinSAD[5];          int32_t iMinSAD[5];
772          SearchData Data;          SearchData Data;
773          Data.iEdgedWidth = pParam->edged_width;          Data.iEdgedWidth = pParam->edged_width;
774          Data.currentMV = currentMV;          Data.currentMV = currentMV;
775            Data.currentQMV = currentQMV;
776          Data.iMinSAD = iMinSAD;          Data.iMinSAD = iMinSAD;
777          Data.temp = temp;          Data.temp = temp;
778          Data.iFcode = current->fcode;          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                                                  &Data, 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 613  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->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 680  Line 936 
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 702  Line 958 
958    
959          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //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, Data->iFcode);                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
962    
963          Data->predMV = pmv[0];          Data->predMV = pmv[0];
964    
965          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
966          Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8;
967            Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8;
968    
969            Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16;
970          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
971          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
972          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;          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->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);
# Line 719  Line 982 
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); }
984    
985          for(i = 0;  i < 5; i++) Data->iMinSAD[i] = 256*4096;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
   
         if (inter4v) CheckCandidate = CheckCandidate16;  
         else CheckCandidate = CheckCandidate16no4v;  
986    
987          (*CheckCandidate)(Data->predMV.x, Data->predMV.y, 0, &iDirection, Data);          for(i = 0;  i < 5; i++)
988                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
989    
990          for(i = 0;  i < 5; i++) Data->currentMV[i].x = Data->currentMV[i].y = 0;          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          i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);          Data->iMinSAD[0] = pMB->sad16 + (Data->lambda16 * i * pMB->sad16)/1000;
996          Data->iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;          Data->iMinSAD[1] = pMB->sad8[0] + (Data->lambda8 * i * (pMB->sad8[0]+NEIGH_8X8_BIAS))/100;
         Data->iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;  
997          Data->iMinSAD[2] = pMB->sad8[1];          Data->iMinSAD[2] = pMB->sad8[1];
998          Data->iMinSAD[3] = pMB->sad8[2];          Data->iMinSAD[3] = pMB->sad8[2];
999          Data->iMinSAD[4] = pMB->sad8[3];          Data->iMinSAD[4] = pMB->sad8[3];
1000    
         if (pMB->dquant != NO_CHANGE) inter4v = 0;  
   
1001          if ((x == 0) && (y == 0)) threshA = 512;          if ((x == 0) && (y == 0)) threshA = 512;
1002          else {          else {
1003                  threshA = Data->temp[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 || pParam->m_quarterpel || Data->chroma) CheckCandidate = CheckCandidate16;
1011            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 (Data->iMinSAD[0] <= threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1019          }          }
1020    
# Line 779  Line 1043 
1043                          if (!(MVequal(startMV, backupMV))) {                          if (!(MVequal(startMV, backupMV))) {
1044                                  bSAD = Data->iMinSAD[0]; Data->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 < Data->iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1049                                          Data->currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
# Line 792  Line 1056 
1056                          if (!(MVequal(startMV, backupMV))) {                          if (!(MVequal(startMV, backupMV))) {
1057                                  bSAD = Data->iMinSAD[0]; Data->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 < Data->iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1062                                          Data->currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
# Line 803  Line 1067 
1067    
1068          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1069    
1070            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                    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                    QuarterpelRefine(Data);
1082            }
1083    
1084            if (Data->iMinSAD[0] < (int32_t)iQuant * 30 ) inter4v = 0;
1085          if (inter4v) {          if (inter4v) {
1086                  SearchData Data8;                  SearchData Data8;
1087                  Data8.iFcode = Data->iFcode;                  Data8.iFcode = Data->iFcode;
1088                  Data8.iQuant = Data->iQuant;                  Data8.lambda8 = Data->lambda8;
1089                  Data8.iEdgedWidth = Data->iEdgedWidth;                  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);                  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);                  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);                  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);                  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) ||
# Line 822  Line 1119 
1119                  pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1120                          = pMB->mvs[2] = pMB->mvs[3] = Data->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] =  Data->iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1127    
1128                    if(pParam->m_quarterpel) {
1129                            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;                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1133                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;                  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 = Data->iMinSAD[1] + Data->iMinSAD[2] +                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1139                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1140          }          }
   
1141  }  }
1142    
1143  static void  static void
# Line 846  Line 1150 
1150                  const int block,                  const int block,
1151                  SearchData * const Data)                  SearchData * const Data)
1152  {  {
         Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);  
1153          Data->iMinSAD = OldData->iMinSAD + 1 + block;          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1154          Data->currentMV = OldData->currentMV + 1 + block;          Data->currentMV = OldData->currentMV + 1 + block;
1155            Data->currentQMV = OldData->currentQMV + 1 + block;
1156    
1157          if (block != 0)          if(pParam->m_quarterpel) {
1158                  *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *                  Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1159                    if (block != 0) *(Data->iMinSAD) += (Data->lambda8 *
1160                                                                            d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1161                                                                                                    Data->currentQMV->y - Data->predQMV.y,
1162                                                                                                    Data->iFcode) * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
1163            } else {
1164                    Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1165                    if (block != 0) *(Data->iMinSAD) += (Data->lambda8 *
1166                                                                  d_mv_bits(      Data->currentMV->x - Data->predMV.x,                                                                  d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1167                                                                                          Data->currentMV->y - Data->predMV.y,                                                                                          Data->currentMV->y - Data->predMV.y,
1168                                                                                          Data->iFcode);                                                                                                  Data->iFcode) * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
1169            }
1170    
1171          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
1172    
# Line 866  Line 1178 
1178                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
1179    
1180                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1181                                  pParam->width, pParam->height, OldData->iFcode);                                  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(*(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                            HalfpelRefine(Data); // perform halfpel refine of current best vector
1204    
1205                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(Data);                          if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1206                                    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;          pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1228          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1229            }
1230    
1231          pMB->mvs[block] = *(Data->currentMV);          pMB->mvs[block] = *(Data->currentMV);
1232          pMB->sad8[block] =  4 * (*Data->iMinSAD);          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 947  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;
1311    
1312          Data.iMinSAD = &iMinSAD;          Data->Ref = pRef + (x + y * iEdgedWidth) * 16;
1313          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->RefH = pRefH + (x + y * iEdgedWidth) * 16;
1314          Data.iEdgedWidth = iEdgedWidth;          Data->RefV = pRefV + (x + y * iEdgedWidth) * 16;
1315          Data.currentMV = &currentMV;          Data->RefHV = pRefHV + (x + y * iEdgedWidth) * 16;
         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;  
1316    
1317          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,          Data->predMV = *predMV;
                                 pParam->width, pParam->height, iFcode);  
   
         if (!(MotionFlags & PMV_HALFPEL16)) {  
                 Data.min_dx = EVEN(Data.min_dx);  
                 Data.max_dx = EVEN(Data.max_dx);  
                 Data.min_dy = EVEN(Data.min_dy);  
                 Data.max_dy = EVEN(Data.max_dy); } // no-halpel and b-frames. do we need it?  
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 1008  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 (iMinSAD < *best_sad) {          if (*Data->iMinSAD < *best_sad) {
1351                  *best_sad = iMinSAD;                  *best_sad = *Data->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  }  }
# Line 1041  Line 1370 
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 = 266*4096, 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->y + (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->y + (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;
1408    
1409                  if (( pMB->mvs[k].x > Data.max_dx ) || ( pMB->mvs[k].x < Data.min_dx )                  if ( ( pMB->b_mvs[k].x > Data->max_dx ) || ( pMB->b_mvs[k].x < Data->min_dx )
1410                          || ( pMB->mvs[k].y > Data.max_dy ) || ( pMB->mvs[k].y < Data.min_dy )                          || ( pMB->b_mvs[k].y > Data->max_dy ) || ( pMB->b_mvs[k].y < Data->min_dy )) {
                         || ( pMB->b_mvs[k].x > Data.max_dx ) || ( pMB->b_mvs[k].x < Data.min_dx )  
                         || ( pMB->b_mvs[k].y > Data.max_dy ) || ( pMB->b_mvs[k].y < Data.min_dy )) {  
1411    
1412                          *best_sad = 256*4096; // in that case, we won't use direct mode                          *best_sad = 256*4096; // in that case, we won't use direct mode
1413                          pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"                          pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
# Line 1100  Line 1417 
1417                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1418                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1419                          pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];                          pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];
1420                          Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1421                          Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1422                          break;                          break;
1423                  }                  }
1424          }          }
# Line 1110  Line 1427 
1427                  CheckCandidate = CheckCandidateDirect;                  CheckCandidate = CheckCandidateDirect;
1428          else CheckCandidate = CheckCandidateDirectno4v;          else CheckCandidate = CheckCandidateDirectno4v;
1429    
1430          (*CheckCandidate)(0, 0, 255, &k, &Data);          (*CheckCandidate)(0, 0, 255, &k, Data);
1431    
1432  // skip decision  // skip decision
1433          if (iMinSAD - 2 * lambda_vec16[iQuant] < (int32_t)iQuant * SKIP_THRESH_B) {          if (*Data->iMinSAD < pMB->quant * SKIP_THRESH_B) {
1434                  //checking chroma. everything copied from MC                  //possible skip - checking chroma. everything copied from MC
1435                  //this is not full chroma compensation, only it's fullpel approximation. should work though                  //this is not full chroma compensation, only it's fullpel approximation. should work though
1436                  int sum, dx, dy, b_dx, b_dy;                  int sum, dx, dy, b_dx, b_dy;
1437    
# Line 1130  Line 1447 
1447                  sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;                  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));                  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*(iEdgedWidth/2),                  sum = sad8bi(pCur->u + 8*x + 8*y*(Data->iEdgedWidth/2),
1451                                          f_Ref->u + (y*8 + dy/2) * (iEdgedWidth/2) + x*8 + dx/2,                                          f_Ref->u + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1452                                          b_Ref->u + (y*8 + b_dy/2) * (iEdgedWidth/2) + x*8 + b_dx/2,                                          b_Ref->u + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1453                                          iEdgedWidth/2);                                          Data->iEdgedWidth/2);
1454                  sum += sad8bi(pCur->v + 8*x + 8*y*(iEdgedWidth/2),                  sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1455                                          f_Ref->v + (y*8 + dy/2) * (iEdgedWidth/2) + x*8 + dx/2,                                          f_Ref->v + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1456                                          b_Ref->v + (y*8 + b_dy/2) * (iEdgedWidth/2) + x*8 + b_dx/2,                                          b_Ref->v + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1457                                          iEdgedWidth/2);                                          Data->iEdgedWidth/2);
1458    
1459                  if ((uint32_t) sum < MAX_CHROMA_SAD_FOR_SKIP * Data.iQuant) {                  if (sum < MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) {
1460                          pMB->mode = MODE_DIRECT_NONE_MV;                          pMB->mode = MODE_DIRECT_NONE_MV;
1461                          return iMinSAD;                          return *Data->iMinSAD;
1462                  }                  }
1463          }          }
1464    
1465          skip_sad = iMinSAD;          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
# Line 1154  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 1199  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;  
1533    
1534          fData.iMinSAD = bData.iMinSAD = &iMinSAD;          *(bData.iMinSAD = fData->iMinSAD) = 4096*256;
1535            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          fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
         fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;  
         fData.currentMV = currentMV; bData.currentMV = currentMV + 1;  
         fData.iQuant = bData.iQuant = iQuant;  
         fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;  
   
         bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  
         bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;  
         bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;  
         bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;  
         bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;  
         bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;  
         bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;  
         bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;  
   
         bData.bpredMV = fData.predMV = *f_predMV;  
         fData.bpredMV = bData.predMV = *b_predMV;  
   
         currentMV[0] = pMB->mvs[0];  
         currentMV[1] = pMB->b_mvs[0];  
         get_range(&fData.min_dx, &fData.max_dx, &fData.min_dy, &fData.max_dy, x, y, 16, pParam->width, pParam->height, fcode);  
         get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode);  
   
         if (currentMV[0].x > fData.max_dx) currentMV[0].x = fData.max_dx;  
         if (currentMV[0].x < fData.min_dx) currentMV[0].x = fData.min_dy;  
         if (currentMV[0].y > fData.max_dy) currentMV[0].y = fData.max_dx;  
         if (currentMV[0].y > fData.min_dy) currentMV[0].y = fData.min_dy;  
   
         if (currentMV[1].x > bData.max_dx) currentMV[1].x = bData.max_dx;  
         if (currentMV[1].x < bData.min_dx) currentMV[1].x = bData.min_dy;  
         if (currentMV[1].y > bData.max_dy) currentMV[1].y = bData.max_dx;  
         if (currentMV[1].y > bData.min_dy) currentMV[1].y = bData.min_dy;  
   
         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 + 1, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1577                  CheckCandidateInt(i, j + 1, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1578                  CheckCandidateInt(i - 1, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1579                  CheckCandidateInt(i, j - 1, 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 + 1, j, 0, &iDirection, &bData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1586                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
# Line 1279  Line 1589 
1589    
1590          } while (!(iDirection));          } while (!(iDirection));
1591    
1592  // two bits are needed to code interpolate mode. we treat the bits just like they were vector's          *fData->iMinSAD +=  2 * fData->lambda16; // two bits are needed to code interpolate mode.
1593          iMinSAD +=  2 * lambda_vec16[iQuant];  
1594          if (iMinSAD < *best_sad) {          if (*fData->iMinSAD < *best_sad) {
1595                  *best_sad = iMinSAD;                  *best_sad = *fData->iMinSAD;
1596                  pMB->mvs[0] = currentMV[0];                  pMB->mvs[0] = fData->currentMV[0];
1597                  pMB->b_mvs[0] = currentMV[1];                  pMB->b_mvs[0] = fData->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 1322  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 1332  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,                          skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
1667                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,                                                                          b_ref, 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    
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 1381  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 1408  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 1482  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;  
1754    
1755          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1756          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,          Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1757                                  pParam->width, pParam->height, iFcode);          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1758                                    pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
1759    
1760          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
1761          Data.iEdgedWidth = iEdgedWidth;          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1762          Data.currentMV = currentMV;          Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1763          Data.iMinSAD = iMinSAD;  
1764          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16;
1765          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
1766          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
1767          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
1768          Data.temp = temp;          Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1769          Data.iQuant = iQuant;          Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
         Data.iFcode = iFcode;  
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 1553  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            for(i = 0; i < 5; i++) {
1813                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1814                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1815            }
1816    
1817          if (inter4v)          if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1818                  for(i = 0; i < 4; i++)                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1819                          Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                                  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->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 1595  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    
# Line 1609  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                          SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchPhinted(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
1942                                                          y, current->motion_flags, pMB->quant,                                                          y, current->motion_flags, pMB->quant,
1943                                                          current->fcode, pParam, pMBs,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
1944                                                          current->global_flags & XVID_INTER4V, pMB);                                                          &Data);
1945    
1946                  }                  }
1947          }          }
1948            free(qimage);
1949  }  }
1950    
1951  static __inline int  static __inline int
# Line 1624  Line 1953 
1953                                  const uint8_t * const pCur,                                  const uint8_t * const pCur,
1954                                  const int x,                                  const int x,
1955                                  const int y,                                  const int y,
                                 const uint32_t iFcode,  
1956                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1957                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1958                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
1959                                    SearchData * const Data)
1960  {  {
1961    
1962          const int32_t iEdgedWidth = pParam->edged_width;          int i = 255, mask;
1963          int i, mask;          VECTOR pmv[3];
         VECTOR currentMV, pmv[3];  
         int32_t iMinSAD = MV_MAX_ERROR;  
         SearchData Data;  
1964    
1965          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          *(Data->iMinSAD) = MV_MAX_ERROR;
1966          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1967                                  pParam->width, pParam->height, iFcode);          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 * iEdgedWidth) * 16;          Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
1971          Data.iEdgedWidth = iEdgedWidth;          Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
         Data.currentMV = &currentMV;  
         Data.iMinSAD = &iMinSAD;  
         Data.Ref = pRef + (x + iEdgedWidth*y)*16;  
         Data.iQuant = 2;  
         Data.iFcode = iFcode;  
1972    
1973          CheckCandidate = CheckCandidate16no4vI;          CheckCandidate = CheckCandidate16no4vI;
1974    
1975          pmv[1].x = EVEN(pMB->mvs[0].x);          pmv[1].x = EVEN(pMB->mvs[0].x);
1976          pmv[1].y = EVEN(pMB->mvs[0].y);          pmv[1].y = EVEN(pMB->mvs[0].y);
1977          pmv[0].x = EVEN(Data.predMV.x);          pmv[0].x = EVEN(Data->predMV.x);
1978          pmv[0].y = EVEN(Data.predMV.y);          pmv[0].y = EVEN(Data->predMV.y);
1979          pmv[2].x = pmv[2].y = 0;          pmv[2].x = pmv[2].y = 0;
1980    
1981          CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, &Data);          CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, Data);
1982          if (!(mask = make_mask(pmv, 1)))          if (!(mask = make_mask(pmv, 1)))
1983                  CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, &Data);                  CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, Data);
1984          if (!(mask = make_mask(pmv, 2)))          if (!(mask = make_mask(pmv, 2)))
1985                  CheckCandidate16no4vI(0, 0, mask, &i, &Data);                  CheckCandidate16no4vI(0, 0, mask, &i, Data);
1986    
1987          DiamondSearch(currentMV.x, currentMV.y, &Data, i);          DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
1988    
1989          pMB->mvs[0] = pMB->mvs[1]          pMB->mvs[0] = *Data->currentMV;
1990                          = pMB->mvs[2] = pMB->mvs[3] = currentMV; // all, for future get_pmv()          pMB->mode = MODE_INTER;
1991    
1992          return iMinSAD;          return *(Data->iMinSAD);
1993  }  }
1994    
1995  #define INTRA_THRESH    1350  #define INTRA_THRESH    1350
# Line 1683  Line 2005 
2005          uint32_t x, y, intra = 0;          uint32_t x, y, intra = 0;
2006          int sSAD = 0;          int sSAD = 0;
2007    
2008            VECTOR currentMV;
2009            int32_t iMinSAD;
2010            SearchData Data;
2011            Data.iEdgedWidth = pParam->edged_width;
2012            Data.currentMV = &currentMV;
2013            Data.iMinSAD = &iMinSAD;
2014            Data.iFcode = iFcode;
2015    
2016          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
2017    
2018          for (y = 0; y < pParam->mb_height-1; y++) {          for (y = 1; y < pParam->mb_height-1; y++) {
2019                  for (x = 0; x < pParam->mb_width; x++) {                  for (x = 1; x < pParam->mb_width-1; x++) {
2020                          int sad, dev;                          int sad, dev;
   
2021                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2022    
2023                          sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,                          sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
2024                                                                  iFcode, pParam, pMBs, pMB);                                                                  pParam, pMBs, pMB, &Data);
2025    
                         if ( x != 0 && y != 0 && x != pParam->mb_width-1 ) { //no edge macroblocks, they just don't work  
2026                                  if (sad > INTRA_THRESH) {                                  if (sad > INTRA_THRESH) {
2027                                          dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                          dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
2028                                                                    pParam->edged_width);                                                                    pParam->edged_width);
2029                                          if (dev + INTRA_THRESH < sad) intra++;                                  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                                          if (intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame
2031                                  }                                  }
2032                                  sSAD += sad;                                  sSAD += sad;
2033                          }                          }
   
                 }  
2034          }          }
2035          sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);          sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2036          if (sSAD > INTER_THRESH ) return 1; //P frame          if (sSAD > INTER_THRESH ) return 1; //P frame
# Line 1712  Line 2038 
2038          return 0; // B frame          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.539  
changed lines
  Added in v.628

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