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

Legend:
Removed from v.539  
changed lines
  Added in v.631

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