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

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

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

revision 530, Mon Sep 23 20:36:02 2002 UTC revision 619, Sat Nov 2 15:52:31 2002 UTC
# Line 37  Line 37 
37  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
38  #include "../global.h"  #include "../global.h"
39  #include "../utils/timer.h"  #include "../utils/timer.h"
40    #include "../image/interpolate8x8.h"
41  #include "motion_est.h"  #include "motion_est.h"
42  #include "motion.h"  #include "motion.h"
43  #include "sad.h"  #include "sad.h"
44    #include "../utils/emms.h"
45    
46  #define INITIAL_SKIP_THRESH     (10)  #define INITIAL_SKIP_THRESH     (10)
47  #define FINAL_SKIP_THRESH       (50)  #define FINAL_SKIP_THRESH       (50)
48  #define MAX_SAD00_FOR_SKIP      (20)  #define MAX_SAD00_FOR_SKIP      (20)
49  #define MAX_CHROMA_SAD_FOR_SKIP (18)  #define MAX_CHROMA_SAD_FOR_SKIP (22)
50  #define SKIP_THRESH_B (10)  #define SKIP_THRESH_B (25)
51    
52  #define CHECK_CANDIDATE(X,Y,D) { \  #define CHECK_CANDIDATE(X,Y,D) { \
53  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }
54    
55  #define iDiamondSize 2  #define GET_REFERENCE(X, Y, REF) { \
56            switch ( (((X)&1)<<1) + ((Y)&1) ) \
57            { \
58                    case 0 : REF = (uint8_t *)data->Ref + (X)/2 + ((Y)/2)*(data->iEdgedWidth); break; \
59                    case 1 : REF = (uint8_t *)data->RefV + (X)/2 + (((Y)-1)/2)*(data->iEdgedWidth); break; \
60                    case 2 : REF = (uint8_t *)data->RefH + ((X)-1)/2 + ((Y)/2)*(data->iEdgedWidth); break; \
61                    default : REF = (uint8_t *)data->RefHV + ((X)-1)/2 + (((Y)-1)/2)*(data->iEdgedWidth); break; \
62            } \
63    }
64    
65  //FILE * debug;  #define iDiamondSize 2
66    
67  static __inline int  static __inline int
68  d_mv_bits(int x, int y, const uint32_t iFcode)  d_mv_bits(int x, int y, const uint32_t iFcode)
# Line 79  Line 89 
89          return xb + yb;          return xb + yb;
90  }  }
91    
92  /* CHACK_CANDIATE FUNCTIONS START */  
93    /* CHECK_CANDIATE FUNCTIONS START */
94    
95  static void  static void
96  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)
97  {  {
         int32_t * const sad = data->temp;  
 //      static int32_t sad[5];  
98          int t;          int t;
99          const uint8_t * Reference;          const uint8_t * Reference;
100    
# Line 99  Line 108 
108                  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;
109          }          }
110    
111          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, sad+1);          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
112    
113          t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
114          data->temp[0] += lambda_vec16[data->iQuant] * t;          data->temp[0] += data->lambda16 * t;
115          data->temp[1] += lambda_vec8[data->iQuant] * t;          data->temp[1] += data->lambda8 * t;
116    
117            if (data->temp[0] < data->iMinSAD[0]) {
118                    data->iMinSAD[0] = data->temp[0];
119                    data->currentMV[0].x = x; data->currentMV[0].y = y;
120                    *dir = Direction; }
121    
122            if (data->temp[1] < data->iMinSAD[1]) {
123                    data->iMinSAD[1] = data->temp[1]; data->currentMV[1].x = x; data->currentMV[1].y = y; }
124            if (data->temp[2] < data->iMinSAD[2]) {
125                    data->iMinSAD[2] = data->temp[2]; data->currentMV[2].x = x; data->currentMV[2].y = y; }
126            if (data->temp[3] < data->iMinSAD[3]) {
127                    data->iMinSAD[3] = data->temp[3]; data->currentMV[3].x = x; data->currentMV[3].y = y; }
128            if (data->temp[4] < data->iMinSAD[4]) {
129                    data->iMinSAD[4] = data->temp[4]; data->currentMV[4].x = x; data->currentMV[4].y = y; }
130    
131    }
132    
133    static void
134    CheckCandidate16Q(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
135    {
136            //this function expects X and Y in halfpel positions, but assumes that qpel positions are our goal
137            int t;
138            const uint8_t * Reference;
139    
140            if (( x > data->max_dx) || ( x < data->min_dx)
141                    || ( y > data->max_dy) || (y < data->min_dy)) return;
142    
143            switch ( ((x&1)<<1) + (y&1) ) {
144                    case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;
145                    case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;
146                    case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;
147                    default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;
148            }
149    
150            data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
151    
152            t = d_mv_bits(2 * x - data->predQMV.x, 2 * y - data->predQMV.y, data->iFcode);
153            data->temp[0] += data->lambda16 * t;
154            data->temp[1] += data->lambda8 * t;
155    
156          if (data->temp[0] < data->iMinSAD[0]) {          if (data->temp[0] < data->iMinSAD[0]) {
157                  data->iMinSAD[0] = data->temp[0];                  data->iMinSAD[0] = data->temp[0];
# Line 138  Line 186 
186                  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;
187          }          }
188    
189          sad = lambda_vec16[data->iQuant] *          sad = data->lambda16 * d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
190                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          sad += sad16(data->Cur, Reference, data->iEdgedWidth, MV_MAX_ERROR);
191          sad += sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);  
192            if (sad < *(data->iMinSAD)) {
193                    *(data->iMinSAD) = sad;
194                    data->currentMV[0].x = x; data->currentMV[0].y = y;
195                    *dir = Direction; }
196    }
197    
198    static void
199    CheckCandidate16_qpel(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
200    
201    // CheckCandidate16 variant which expects x and y in quarter pixel resolution
202    // Important: This is no general usable routine! x and y must be +/-1 (qpel resolution!)
203    // around currentMV!
204    {
205            int t;
206            uint8_t * Reference = (uint8_t *)data->RefQ;
207            const uint8_t *ref1, *ref2, *ref3, *ref4;
208            VECTOR halfpelMV = *(data->currentMV);
209    
210            int32_t iEdgedWidth = data->iEdgedWidth;
211            uint32_t rounding = data->rounding;
212    
213            if (( x > data->max_dx) || ( x < data->min_dx)
214                    || ( y > data->max_dy) || (y < data->min_dy)) return;
215    
216            GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1); // this refenrence is used in all cases
217            switch( ((x&1)<<1) + (y&1) )
218            {
219            case 0: // pure halfpel position - shouldn't happen during a refinement step
220                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, Reference);
221                    break;
222    
223            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
224                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
225                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
226                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding);
227                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding);
228                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding);
229                    break;
230    
231            case 2: // x qpel, y halfpel - left or right during qpel refinement
232                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref2);
233                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
234                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding);
235                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding);
236                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding);
237                    break;
238    
239            default: // x and y in qpel resolution - the "corners" (top left/right and
240                             // bottom left/right) during qpel refinement
241                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
242                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref3);
243                    GET_REFERENCE(x - halfpelMV.x, y - halfpelMV.y, ref4);
244    
245                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
246                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
247                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
248                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
249                    break;
250            }
251    
252            data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp+1);
253    
254            t = d_mv_bits(x - data->predQMV.x, y - data->predQMV.y, data->iFcode);
255            data->temp[0] += data->lambda16 * t;
256            data->temp[1] += data->lambda8 * t;
257    
258            if (data->temp[0] < data->iMinSAD[0]) {
259                    data->iMinSAD[0] = data->temp[0];
260                    data->currentQMV[0].x = x; data->currentQMV[0].y = y;
261            /*      *dir = Direction;*/ }
262    
263            if (data->temp[1] < data->iMinSAD[1]) {
264                    data->iMinSAD[1] = data->temp[1]; data->currentQMV[1].x = x; data->currentQMV[1].y = y; }
265            if (data->temp[2] < data->iMinSAD[2]) {
266                    data->iMinSAD[2] = data->temp[2]; data->currentQMV[2].x = x; data->currentQMV[2].y = y; }
267            if (data->temp[3] < data->iMinSAD[3]) {
268                    data->iMinSAD[3] = data->temp[3]; data->currentQMV[3].x = x; data->currentQMV[3].y = y; }
269            if (data->temp[4] < data->iMinSAD[4]) {
270                    data->iMinSAD[4] = data->temp[4]; data->currentQMV[4].x = x; data->currentQMV[4].y = y; }
271    }
272    
273    static void
274    CheckCandidate16no4vI(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
275    {
276            int32_t sad;
277    
278            if (( x > data->max_dx) || ( x < data->min_dx)
279                    || ( y > data->max_dy) || (y < data->min_dy)) return;
280    
281            sad = sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),
282                                            data->iEdgedWidth, 256*4096);
283    
284          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
285                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 148  Line 287 
287                  *dir = Direction; }                  *dir = Direction; }
288  }  }
289    
290    
291  static void  static void
292  CheckCandidateInt(const int xf, const int yf, const int Direction, int * const dir, const SearchData * const data)  CheckCandidateInt(const int xf, const int yf, const int Direction, int * const dir, const SearchData * const data)
293  {  {
# Line 173  Line 313 
313                  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;
314          }          }
315    
316          sad = lambda_vec16[data->iQuant] *          sad = data->lambda16 *
317                          ( d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode) +                          ( d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode) +
318                            d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode) );                            d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode) );
319    
# Line 196  Line 336 
336    
337          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
338    
339          sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);          sad = data->lambda16 * d_mv_bits(x, y, 1);
340    
341          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
342                  mvs.x = data->directmvF[k].x + x;                  mvs.x = data->directmvF[k].x + x;
# Line 249  Line 389 
389          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
390          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
391    
392          if (( x > 31) || ( x < -31) || ( y > 31) || (y < -31)) return;          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
393    
394                  sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);                  sad = data->lambda16 * d_mv_bits(x, y, 1);
395    
396          mvs.x = data->directmvF[0].x + x;          mvs.x = data->directmvF[0].x + x;
397          b_mvs.x = ((x == 0) ?          b_mvs.x = ((x == 0) ?
# Line 308  Line 448 
448          }          }
449    
450          sad = sad8(data->Cur, Reference, data->iEdgedWidth);          sad = sad8(data->Cur, Reference, data->iEdgedWidth);
451          sad += lambda_vec8[data->iQuant] * d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          sad += data->lambda8 * d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
452    
453            if (sad < *(data->iMinSAD)) {
454                    *(data->iMinSAD) = sad;
455                    data->currentMV->x = x; data->currentMV->y = y;
456                    *dir = Direction; }
457    }
458    
459    static void
460    CheckCandidate8Q(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
461    {
462            int32_t sad;
463            const uint8_t * Reference;
464    
465            if (( x > data->max_dx) || ( x < data->min_dx)
466                    || ( y > data->max_dy) || (y < data->min_dy)) return;
467    
468            switch ( ((x&1)<<1) + (y&1) )
469            {
470                    case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;
471                    case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;
472                    case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;
473                    default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;
474            }
475    
476            sad = sad8(data->Cur, Reference, data->iEdgedWidth);
477            sad += data->lambda8 * d_mv_bits(2 * x - data->predQMV.x, 2 * y - data->predQMV.y, data->iFcode);
478    
479          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
480                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 316  Line 482 
482                  *dir = Direction; }                  *dir = Direction; }
483  }  }
484    
485  /* CHACK_CANDIATE FUNCTIONS END */  static void
486    CheckCandidate8_qpel(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
487    // CheckCandidate16no4v variant which expects x and y in quarter pixel resolution
488    // Important: This is no general usable routine! x and y must be +/-1 (qpel resolution!)
489    // around currentMV!
490    
491    {
492            int32_t sad;
493            uint8_t *Reference = (uint8_t *) data->RefQ;
494            const uint8_t *ref1, *ref2, *ref3, *ref4;
495            VECTOR halfpelMV = *(data->currentMV);
496    
497            int32_t iEdgedWidth = data->iEdgedWidth;
498            uint32_t rounding = data->rounding;
499    
500            if (( x > data->max_dx) || ( x < data->min_dx)
501                    || ( y > data->max_dy) || (y < data->min_dy)) return;
502    
503            GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
504            switch( ((x&1)<<1) + (y&1) )
505            {
506            case 0: // pure halfpel position - shouldn't happen during a refinement step
507                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, Reference);
508                    break;
509    
510            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
511                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
512    
513                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
514                    break;
515    
516            case 2: // x qpel, y halfpel - left or right during qpel refinement
517                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref2);
518    
519                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
520                    break;
521    
522            default: // x and y in qpel resolution - the "corners" (top left/right and
523                             // bottom left/right) during qpel refinement
524                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
525                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref3);
526                    GET_REFERENCE(x - halfpelMV.x, y - halfpelMV.y, ref4);
527    
528                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
529                    break;
530            }
531    
532            sad = sad8(data->Cur, Reference, data->iEdgedWidth);
533            sad += data->lambda8 * d_mv_bits(x - data->predQMV.x, y - data->predQMV.y, data->iFcode);
534    
535            if (sad < *(data->iMinSAD)) {
536                    *(data->iMinSAD) = sad;
537                    data->currentQMV->x = x; data->currentQMV->y = y;
538                    *dir = Direction; }
539    }
540    
541    /* CHECK_CANDIATE FUNCTIONS END */
542    
543  /* MAINSEARCH FUNCTIONS START */  /* MAINSEARCH FUNCTIONS START */
544    
# Line 484  Line 706 
706          CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);          CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);
707  }  }
708    
709    
710    static void
711    QuarterpelRefine(const SearchData * const data)
712    {
713    /* Perform quarter pixel refinement*/
714    
715            VECTOR backupMV = *(data->currentQMV);
716            int iDirection; //not needed
717    
718            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);
719            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);
720            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);
721            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y + 1, 0);
722    
723            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y, 0);
724            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y, 0);
725    
726            CHECK_CANDIDATE(backupMV.x, backupMV.y + 1, 0);
727            CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);
728    
729    }
730    
731  static __inline int  static __inline int
732  SkipDecisionP(const IMAGE * current, const IMAGE * reference,  SkipDecisionP(const IMAGE * current, const IMAGE * reference,
733                                                          const int x, const int y,                                                          const int x, const int y,
# Line 497  Line 741 
741          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,
742                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);
743          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
744          sadC += sad8(current->v + x*8 + y*(iEdgedWidth/2)*8,          sadC += sad8(current->v + (x + y*(iEdgedWidth/2))*8,
745                                          reference->v + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                          reference->v + (x + y*(iEdgedWidth/2))*8, iEdgedWidth/2);
746          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
747    
748          return 1;          return 1;
# Line 508  Line 752 
752  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)
753  {  {
754          pMB->mode = MODE_NOT_CODED;          pMB->mode = MODE_NOT_CODED;
755          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = pMB->mv16.x = 0;          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;
756          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = pMB->mv16.y = 0;          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;
757            pMB->qmvs[0].x = pMB->qmvs[1].x = pMB->qmvs[2].x = pMB->qmvs[3].x = 0;
758            pMB->qmvs[0].y = pMB->qmvs[1].y = pMB->qmvs[2].y = pMB->qmvs[3].y = 0;
759    
760          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;
761  }  }
762    
# Line 530  Line 777 
777    
778          uint32_t x, y;          uint32_t x, y;
779          uint32_t iIntra = 0;          uint32_t iIntra = 0;
780          int32_t InterBias;          int32_t InterBias, quant = current->quant;
781            uint8_t *qimage;
782    
783            // some pre-initialized thingies for SearchP
784            int32_t temp[5];
785            VECTOR currentMV[5];
786            VECTOR currentQMV[5];
787            int32_t iMinSAD[5];
788            SearchData Data;
789            Data.iEdgedWidth = pParam->edged_width;
790            Data.currentMV = currentMV;
791            Data.currentQMV = currentQMV;
792            Data.iMinSAD = iMinSAD;
793            Data.temp = temp;
794            Data.iFcode = current->fcode;
795            Data.rounding = pParam->m_rounding_type;
796    
797            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
798                    return 1; // allocate some mem for qpel interpolated blocks
799                                      // somehow this is dirty since I think we shouldn't use malloc outside
800                                      // encoder_create() - so please fix me!
801    
802          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
803    
# Line 545  Line 812 
812    
813                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
814                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
815                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant;
816                            } else {
817                                    if (pMB->dquant != NO_CHANGE) {
818                                            quant += DQtab[pMB->dquant];
819                                            if (quant > 31) quant = 31;
820                                            else if (quant < 1) quant = 1;
821                                    }
822                                    pMB->quant = quant;
823                            }
824    
825  //initial skip decision  /* initial skip decision */
826    /* no early skip for GMC (global vector = skip vector is unknown!)  */
827    
828                          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 */
829                                  && (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) ) {                                  if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * INITIAL_SKIP_THRESH)
830                                  if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {                                          if (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
831                                                  SkipMacroblockP(pMB, sad00);                                                  SkipMacroblockP(pMB, sad00);
832                                                  continue;                                                  continue;
833                                  }                                  }
834                          } else sad00 = 256*4096; // skip not allowed - for final skip decision                          }
835    
836                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, qimage, pCurrent, x,
837                                                  y, current->motion_flags, pMB->quant,                                                  y, current->motion_flags, pMB->quant,
838                                                  current->fcode, pParam, pMBs, reference->mbs,                                                  &Data, pParam, pMBs, reference->mbs,
839                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
840    
841  /* 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?" */
842                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)                          if (current->coding_type == P_VOP)      {
843                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)                                  if ( (pMB->dquant == NO_CHANGE) && (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)
844                                  { SkipMacroblockP(pMB, sad00); continue; }                                  && ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH) )
845                                            if (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
846                                                    SkipMacroblockP(pMB, sad00);
847                                                    continue;
848                                            }
849                            }
850    
851  /* finally, intra decision */  /* finally, intra decision */
852    
# Line 582  Line 863 
863                                                    pParam->edged_width);                                                    pParam->edged_width);
864    
865                                  if (deviation < (pMB->sad16 - InterBias)) {                                  if (deviation < (pMB->sad16 - InterBias)) {
866                                          if (++iIntra >= iLimit) return 1;                                          if (++iIntra >= iLimit) { free(qimage); return 1; }
867                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
868                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
869                                                  pMB->mvs[3] = zeroMV;                                                  pMB->mvs[3] = zeroMV;
870                                            pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] =
871                                                            pMB->qmvs[3] = zeroMV;
872                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
873                                                  pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
874                                  }                                  }
875                          }                          }
876                  }                  }
877          }          }
878            free(qimage);
879    
880            if (current->coding_type == S_VOP)      /* first GMC step only for S(GMC)-VOPs */
881                    current->GMC_MV = GlobalMotionEst( pMBs, pParam, current->fcode );
882            else
883                    current->GMC_MV = zeroMV;
884    
885          return 0;          return 0;
886  }  }
887    
# Line 601  Line 891 
891  static __inline int  static __inline int
892  make_mask(const VECTOR * const pmv, const int i)  make_mask(const VECTOR * const pmv, const int i)
893  {  {
894          int mask = 0xFF, j;          int mask = 255, j;
895          for (j = 0; j < i; j++) {          for (j = 0; j < i; j++) {
896                  if (MVequal(pmv[i], pmv[j])) return 0; // same vector has been checked already                  if (MVequal(pmv[i], pmv[j])) return 0; // same vector has been checked already
897                  if (pmv[i].x == pmv[j].x) {                  if (pmv[i].x == pmv[j].x) {
# Line 625  Line 915 
915    
916          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour
917                  pmv[5].x = EVEN(pmv[3].x);                  pmv[5].x = EVEN(pmv[3].x);
918                  pmv[5].y = EVEN(pmv[3].y); }                  pmv[5].y = EVEN(pmv[3].y);
919          else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
920    
921          if (x != 0) { pmv[3].x = EVEN(pmv[1].x); pmv[3].y = EVEN(pmv[1].y); }// pmv[3] is left neighbour          if (x != 0) { pmv[3].x = EVEN(pmv[1].x); pmv[3].y = EVEN(pmv[1].y); }// pmv[3] is left neighbour
922          else pmv[3].x = pmv[3].y = 0;          else pmv[3].x = pmv[3].y = 0;
# Line 644  Line 934 
934    
935          if ((x != iWcount-1) && (y != iHcount-1)) {          if ((x != iWcount-1) && (y != iHcount-1)) {
936                  pmv[6].x = EVEN((prevMB+1+iWcount)->mvs[0].x); //[6] right-down neighbour in last frame                  pmv[6].x = EVEN((prevMB+1+iWcount)->mvs[0].x); //[6] right-down neighbour in last frame
937                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y); }                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
938          else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
939  }  }
940    
941  static void  static void
# Line 653  Line 943 
943                  const uint8_t * const pRefH,                  const uint8_t * const pRefH,
944                  const uint8_t * const pRefV,                  const uint8_t * const pRefV,
945                  const uint8_t * const pRefHV,                  const uint8_t * const pRefHV,
946                    const uint8_t * const pRefQ,
947                  const IMAGE * const pCur,                  const IMAGE * const pCur,
948                  const int x,                  const int x,
949                  const int y,                  const int y,
950                  const uint32_t MotionFlags,                  const uint32_t MotionFlags,
951                  const uint32_t iQuant,                  const uint32_t iQuant,
952                  const uint32_t iFcode,                  SearchData * const Data,
953                  const MBParam * const pParam,                  const MBParam * const pParam,
954                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
955                  const MACROBLOCK * const prevMBs,                  const MACROBLOCK * const prevMBs,
# Line 666  Line 957 
957                  MACROBLOCK * const pMB)                  MACROBLOCK * const pMB)
958  {  {
959    
         const int32_t iEdgedWidth = pParam->edged_width;  
   
960          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
961          int32_t temp[5];          VECTOR pmv[7];
         VECTOR currentMV[5], pmv[7];  
         int32_t psad[4], iMinSAD[5];  
         MainSearchFunc * MainSearchPtr;  
         SearchData Data;  
962    
963          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, psad);  //has to be changed to get_pmv(2)()          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()
964          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,
965                                  pParam->width, pParam->height, iFcode);                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
966    
967          Data.predMV = pmv[0];          Data->predMV = pmv[0];
968          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
969          Data.iEdgedWidth = iEdgedWidth;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
970          Data.currentMV = currentMV;          Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;
971          Data.iMinSAD = iMinSAD;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
972          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
973          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
974          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->RefQ = pRefQ;
         Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;  
         Data.temp = temp;  
975    
976          Data.iQuant = iQuant;          Data->lambda16 = lambda_vec16[iQuant];
977          Data.iFcode = iFcode;          Data->lambda8 = lambda_vec8[iQuant];
978    
979          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
980                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
981                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
982                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
983                  Data.max_dy = EVEN(Data.max_dy); }                  Data->max_dy = EVEN(Data->max_dy); }
   
         for(i = 0;  i < 5; i++) currentMV[i].x = currentMV[i].y = 0;  
   
         i = d_mv_bits(pmv[0].x, pmv[0].y, iFcode);  
   
         iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;  
         iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;  
         iMinSAD[2] = pMB->sad8[1];  
         iMinSAD[3] = pMB->sad8[2];  
         iMinSAD[4] = pMB->sad8[3];  
984    
985          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
986    
987            for(i = 0;  i < 5; i++)
988                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
989    
990            if (pParam->m_quarterpel) {
991                    Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
992                    i = d_mv_bits(Data->predQMV.x, Data->predQMV.y, Data->iFcode);
993            } else i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);
994    
995            Data->iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;
996            Data->iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;
997            Data->iMinSAD[2] = pMB->sad8[1];
998            Data->iMinSAD[3] = pMB->sad8[2];
999            Data->iMinSAD[4] = pMB->sad8[3];
1000    
1001          if ((x == 0) && (y == 0)) threshA = 512;          if ((x == 0) && (y == 0)) threshA = 512;
1002          else {          else {
1003                  threshA = psad[0] + 20;                  threshA = Data->temp[0]; // that's when we keep this SAD atm
1004                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
1005                  if (threshA > 1024) threshA = 1024; }                  if (threshA > 1024) threshA = 1024; }
1006    
1007          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,
1008                                          prevMBs + x + y * pParam->mb_width);                                          prevMBs + x + y * pParam->mb_width);
1009    
1010            if (pParam->m_quarterpel) CheckCandidate = CheckCandidate16Q;
1011            else
1012          if (inter4v) CheckCandidate = CheckCandidate16;          if (inter4v) CheckCandidate = CheckCandidate16;
1013          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
1014    
# Line 727  Line 1016 
1016    
1017          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
1018                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1019                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  (*CheckCandidate)(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1020                  if (iMinSAD[0] < threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1021          }          }
1022    
1023          if ((iMinSAD[0] <= threshA) ||          if ((Data->iMinSAD[0] <= threshA) ||
1024                          (MVequal(currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
1025                          (iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {                          (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {
1026                  inter4v = 0;                  inter4v = 0;
1027                  if (MotionFlags & PMV_QUICKSTOP16) goto PMVfast16_Terminate_without_Refine;          } else {
                 if (MotionFlags & PMV_EARLYSTOP16) {  
                         CheckCandidate = CheckCandidate16no4v; // I sure hope it's faster  
                         goto PMVfast16_Terminate_with_Refine;  
                 }  
         }  
1028    
1029          if (MotionFlags & PMV_USESQUARES16)                  MainSearchFunc * MainSearchPtr;
1030                  MainSearchPtr = SquareSearch;                  if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
1031          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
                 MainSearchPtr = AdvDiamondSearch;  
1032                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1033    
1034          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, iDirection);                  (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1035    
1036  /* extended search, diamond starting in 0,0 and in prediction.  /* extended search, diamond starting in 0,0 and in prediction.
1037          note that this search is/might be done in halfpel positions,          note that this search is/might be done in halfpel positions,
# Line 756  Line 1039 
1039    
1040          if (MotionFlags & PMV_EXTSEARCH16) {          if (MotionFlags & PMV_EXTSEARCH16) {
1041                  int32_t bSAD;                  int32_t bSAD;
1042                  VECTOR startMV = Data.predMV, backupMV = currentMV[0];                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
1043                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?
1044                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);
1045                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1046                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1047    
1048                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1049                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1050                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1051                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1052                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1053                  }                  }
1054    
1055                  backupMV = currentMV[0];                          backupMV = Data->currentMV[0];
1056                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;
1057                  else startMV.x = startMV.y = 0;                  else startMV.x = startMV.y = 0;
1058                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1059                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1060    
1061                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1062                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1063                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1064                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1065                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1066                            }
1067                  }                  }
1068          }          }
1069    
1070  PMVfast16_Terminate_with_Refine:          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1071    
1072          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          for(i = 0; i < 5; i++) {
1073                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1074                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1075            }
1076    
1077  PMVfast16_Terminate_without_Refine:          if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1078    
1079          if (inter4v)                  CheckCandidate = CheckCandidate16_qpel;
1080                  for(i = 0; i < 4; i++)                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1081                          Search8(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                                  pParam->width, pParam->height, Data->iFcode, 0);
1082    
1083                    QuarterpelRefine(Data);
1084            }
1085    
1086            if (inter4v) {
1087                    SearchData Data8;
1088                    Data8.iFcode = Data->iFcode;
1089                    Data8.lambda8 = Data->lambda8;
1090                    Data8.iEdgedWidth = Data->iEdgedWidth;
1091                    Data8.RefQ = Data->RefQ;
1092                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1093                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1094                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1095                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1096            }
1097    
1098          if (!(inter4v) ||          if (!(inter4v) ||
1099                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
1100                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1101  // INTER MODE  // INTER MODE
1102                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1103                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1104                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1105    
1106                    pMB->qmvs[0] = pMB->qmvs[1]
1107                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1108    
1109                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1110                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1111    
1112                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1113                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predQMV.x;
1114                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predQMV.y;
1115                    }
1116                    else {
1117                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1118                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1119                    }
1120          } else {          } else {
1121  // INTER4V MODE; all other things are already set in Search8  // INTER4V MODE; all other things are already set in Search8
1122                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1123                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1124                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1125          }          }
   
1126  }  }
1127    
1128  static void  static void
# Line 820  Line 1132 
1132                  const MBParam * const pParam,                  const MBParam * const pParam,
1133                  MACROBLOCK * const pMB,                  MACROBLOCK * const pMB,
1134                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
1135                  const int block)                  const int block,
1136                    SearchData * const Data)
1137  {  {
1138          SearchData Data;          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1139            Data->currentMV = OldData->currentMV + 1 + block;
1140          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          Data->currentQMV = OldData->currentQMV + 1 + block;
1141          Data.iMinSAD = OldData->iMinSAD + 1 + block;  
1142          Data.currentMV = OldData->currentMV+1+block;          if(pParam->m_quarterpel) {
1143          Data.iFcode = OldData->iFcode;                  Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1144          Data.iQuant = OldData->iQuant;                  if (block != 0) *(Data->iMinSAD) += Data->lambda8 *
1145                                                                            d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1146          if (block != 0)                                                                                                  Data->currentQMV->y - Data->predQMV.y,
1147                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *                                                                                                  Data->iFcode);
1148                                                                  d_mv_bits(      Data.currentMV->x - Data.predMV.x,                  CheckCandidate = CheckCandidate8Q;
1149                                                                                          Data.currentMV->y - Data.predMV.y,          } else {
1150                                                                                          Data.iFcode);                  Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1151                    if (block != 0) *(Data->iMinSAD) += Data->lambda8 *
1152                                                                            d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1153                                                                                                    Data->currentMV->y - Data->predMV.y,
1154                                                                                                    Data->iFcode);
1155                    CheckCandidate = CheckCandidate8;
1156            }
1157    
1158          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
1159    
1160                  Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));
1161                  Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));
1162                  Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1163                  Data.RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));
   
                 Data.iEdgedWidth = pParam->edged_width;  
   
                 Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));  
1164    
1165                  get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
                                 pParam->width, pParam->height, OldData->iFcode);  
1166    
1167                  CheckCandidate = CheckCandidate8;                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1168                                    pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1169    
1170                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & PMV_EXTSEARCH8) {
1171                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1172    
1173                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1174                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1175                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1176                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1177    
1178                          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);     }                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1179    
1180                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                          if(*(Data->iMinSAD) < temp_sad) {
1181                                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1182                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1183                            }
1184          }          }
1185    
1186          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;                  if (MotionFlags & PMV_HALFPELREFINE8) {
1187          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;                          int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1188          pMB->mvs[block] = *(Data.currentMV);  
1189          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                          HalfpelRefine(Data); // perform halfpel refine of current best vector
1190    
1191                            if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1192                                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1193                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1194                            }
1195                    }
1196    
1197                    if(pParam->m_quarterpel) {
1198                            if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1199                                    (MotionFlags & PMV_QUARTERPELREFINE8)) {
1200                            CheckCandidate = CheckCandidate8_qpel;
1201                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1202                                    pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1203                            QuarterpelRefine(Data);
1204                            }
1205                    }
1206            }
1207    
1208            if(pParam->m_quarterpel) {
1209                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predQMV.x;
1210                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predQMV.y;
1211            }
1212            else {
1213                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1214                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1215            }
1216    
1217            pMB->mvs[block] = *(Data->currentMV);
1218            pMB->qmvs[block] = *(Data->currentQMV);
1219    
1220            pMB->sad8[block] =  4 * (*Data->iMinSAD);
1221  }  }
1222    
1223  /* B-frames code starts here */  /* B-frames code starts here */
# Line 896  Line 1245 
1245          pmv[2] = ChoosePred(pMB, mode_curr);          pmv[2] = ChoosePred(pMB, mode_curr);
1246          pmv[2].x = EVEN(pmv[2].x); pmv[2].y = EVEN(pmv[2].y);          pmv[2].x = EVEN(pmv[2].x); pmv[2].y = EVEN(pmv[2].y);
1247    
         pmv[3].x = pmv[3].y = 0;  
1248          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour
1249                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);
1250                  pmv[3].x = EVEN(pmv[3].x); pmv[3].y = EVEN(pmv[3].y); }                  pmv[3].x = EVEN(pmv[3].x); pmv[3].y = EVEN(pmv[3].y);
1251            } else pmv[3].x = pmv[3].y = 0;
1252    
1253          if (y != 0) {          if (y != 0) {
1254                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);
# Line 929  Line 1278 
1278                          const IMAGE * const pCur,                          const IMAGE * const pCur,
1279                          const int x, const int y,                          const int x, const int y,
1280                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
1281                          const uint32_t iFcode,                          const uint32_t iFcode,
1282                          const MBParam * const pParam,                          const MBParam * const pParam,
1283                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
1284                          const VECTOR * const predMV,                          const VECTOR * const predMV,
1285                          int32_t * const best_sad,                          int32_t * const best_sad,
1286                          const int32_t mode_current)                          const int32_t mode_current,
1287                            SearchData * const Data)
1288  {  {
1289    
1290          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1291    
1292          int i, iDirection, mask;          int i, iDirection, mask;
1293          VECTOR currentMV, pmv[7];          VECTOR pmv[7];
1294          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1295          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
1296          SearchData Data;          Data->iFcode = iFcode;
1297    
1298          Data.iMinSAD = &iMinSAD;          Data->Ref = pRef + (x + y * iEdgedWidth) * 16;
1299          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->RefH = pRefH + (x + y * iEdgedWidth) * 16;
1300          Data.iEdgedWidth = iEdgedWidth;          Data->RefV = pRefV + (x + y * iEdgedWidth) * 16;
1301          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;  
1302    
1303          Data.iQuant = iQuant;          Data->predMV = *predMV;
         Data.iFcode = iFcode;  
         Data.predMV = *predMV;  
   
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,  
                                 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?  
1304    
1305            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1306                                    pParam->width, pParam->height, iFcode, pParam->m_quarterpel);
1307    
1308          pmv[0] = Data.predMV;          pmv[0] = Data->predMV;
1309          PreparePredictionsBF(pmv, x, y, pParam->mb_width,          PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
                                         pMB, mode_current);  
1310    
1311          currentMV.x = currentMV.y = 0;          Data->currentMV->x = Data->currentMV->y = 0;
1312    
1313          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1314    
1315  // main loop. checking all predictions  // main loop. checking all predictions
1316          for (i = 0; i < 8; i++) {          for (i = 0; i < 8; i++) {
1317                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1318                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1319          }          }
1320    
1321          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 990  Line 1324 
1324                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1325                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1326    
1327          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1328    
1329          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          HalfpelRefine(Data);
1330    
1331  // three bits are needed to code backward mode. four for forward  // three bits are needed to code backward mode. four for forward
1332  // we treat the bits just like they were vector's  // we treat the bits just like they were vector's
1333          if (mode_current == MODE_FORWARD) iMinSAD +=  4 * lambda_vec16[iQuant];          if (mode_current == MODE_FORWARD) *Data->iMinSAD +=  4 * Data->lambda16 * 2;
1334          else iMinSAD +=  3 * lambda_vec16[iQuant];          else *Data->iMinSAD +=  3 * Data->lambda16 * 2;
1335    
1336            if (*Data->iMinSAD < *best_sad) {
1337          if (iMinSAD < *best_sad) {                  *best_sad = *Data->iMinSAD;
                 *best_sad = iMinSAD;  
1338                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1339                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1340                  pMB->pmvs[0].y = currentMV.y - predMV->y;                  pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1341                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = *(Data->currentMV+2) = *Data->currentMV;
1342                  else pMB->b_mvs[0] = currentMV;                  else pMB->b_mvs[0] = *(Data->currentMV+1) = *Data->currentMV; //we store currmv for interpolate search
1343          }          }
1344    
1345  }  }
1346    
1347  static int32_t  static int32_t
1348  SearchDirect(const uint8_t * const f_Ref,  SearchDirect(const IMAGE * const f_Ref,
1349                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1350                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
1351                                  const uint8_t * const f_RefHV,                                  const uint8_t * const f_RefHV,
1352                                  const uint8_t * const b_Ref,                                  const IMAGE * const b_Ref,
1353                                  const uint8_t * const b_RefH,                                  const uint8_t * const b_RefH,
1354                                  const uint8_t * const b_RefV,                                  const uint8_t * const b_RefV,
1355                                  const uint8_t * const b_RefHV,                                  const uint8_t * const b_RefHV,
1356                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1357                                  const int x, const int y,                                  const int x, const int y,
1358                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1359                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1360                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1361                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1362                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1363                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1364                                    SearchData * const Data)
1365    
1366  {  {
1367          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
         int32_t iMinSAD = 0, skip_sad;  
1368          int k;          int k;
1369          VECTOR currentMV;  
1370          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
         SearchData Data;  
1371    
1372          Data.iMinSAD = &iMinSAD;          *Data->iMinSAD = 256*4096;
1373          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;  
1374    
1375          Data.Ref= f_Ref + (x + iEdgedWidth*y) * 16;          Data->Ref = f_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1376          Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;          Data->RefH = f_RefH + (x + Data->iEdgedWidth*y) * 16;
1377          Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;          Data->RefV = f_RefV + (x + Data->iEdgedWidth*y) * 16;
1378          Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = f_RefHV + (x + Data->iEdgedWidth*y) * 16;
1379          Data.bRef = b_Ref + (x + iEdgedWidth*y) * 16;          Data->bRef = b_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1380          Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;          Data->bRefH = b_RefH + (x + Data->iEdgedWidth*y) * 16;
1381          Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;          Data->bRefV = b_RefV + (x + Data->iEdgedWidth*y) * 16;
1382          Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;          Data->bRefHV = b_RefHV + (x + Data->iEdgedWidth*y) * 16;
1383  /*  
1384  //What we do here is a complicated version of CheckCandidateDirect(0,0);          Data->max_dx = 2 * pParam->width - 2 * (x) * 16;
1385  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;
1386            Data->min_dx = -(2 * 16 + 2 * (x) * 16);
1387  */          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);  
1388    
1389          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1390                  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);
1391                  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;
1392                  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);
1393                  pMB->b_mvs[k].y = Data.directmvB[k].y = ((TRB - TRD) * Data.referencemv[k].y) / TRD;                  pMB->b_mvs[k].y = Data->directmvB[k].y = ((TRB - TRD) * Data->referencemv[k].y) / TRD;
   
         if (( pMB->mvs[k].x > Data.max_dx ) || ( pMB->mvs[k].x < Data.min_dx )  
                         || ( pMB->mvs[k].y > Data.max_dy ) || ( pMB->mvs[k].y < Data.min_dy )  
                         || ( pMB->b_mvs[k].x > Data.max_dx ) || ( pMB->b_mvs[k].x < Data.min_dx )  
                         || ( pMB->b_mvs[k].y > Data.max_dy ) || ( pMB->b_mvs[k].y < Data.min_dy )) {  
 /*  
                 fprintf(debug, "\nERROR - out of range : vector %d,%d and %d,%d\n", pMB->mvs[k].x, pMB->mvs[k].y,pMB->b_mvs[k].x,pMB->b_mvs[k].y );  
                 fprintf(debug, " range is x: %d..%d y: %d..%d \n", Data.min_dx,Data.max_dx,Data.min_dy,Data.max_dy);  
                 fprintf(debug,"macroblock %d, %d \n", x, y);  
                 fprintf(debug, "direct MV is %d,%d \n", directmv[k].x, directmv[k].y);  
 */  
                 *best_sad = 256*4096; // in that case, we won't use direct mode  
                 pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"  
                 pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;  /* because backwards and interpol might rely on this */  
                 return 0; }  
1394    
1395                    if ( ( pMB->b_mvs[k].x > Data->max_dx ) || ( pMB->b_mvs[k].x < Data->min_dx )
1396                            || ( pMB->b_mvs[k].y > Data->max_dy ) || ( pMB->b_mvs[k].y < Data->min_dy )) {
1397    
1398                            *best_sad = 256*4096; // in that case, we won't use direct mode
1399                            pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
1400                            pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;
1401                            return 0;
1402                    }
1403          if (b_mb->mode != MODE_INTER4V) {          if (b_mb->mode != MODE_INTER4V) {
1404                  iMinSAD = sad16bi(Data.Cur,                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1405                                                  get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,                          pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];
1406                                                                  x, y, 16, &pMB->mvs[0], iEdgedWidth),                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1407                                                  get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1408                                                                  x, y, 16, &pMB->b_mvs[0], iEdgedWidth), iEdgedWidth);                          break;
1409                    }
                 Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];  
                 Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];  
                 break;  
         }  
         iMinSAD += sad8bi(Data.Cur + (k&1)*8 + (k>>1)* 8 * iEdgedWidth,  
                                                 get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,  
                                                                 (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->mvs[k], iEdgedWidth),  
                                                 get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,  
                                                                 (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->b_mvs[k], iEdgedWidth),  
                                                 iEdgedWidth);  
1410          }          }
1411    
 // skip decision  
         if (iMinSAD < (int32_t)iQuant * SKIP_THRESH_B) {  
                 pMB->mode = MODE_DIRECT_NONE_MV;  
                 return iMinSAD; }  
   
         skip_sad = iMinSAD;  
         iMinSAD += 2 * lambda_vec16[iQuant]; // 2 bits needed to code vector 0,0  
         currentMV.x = currentMV.y = 0;  
1412          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1413                  CheckCandidate = CheckCandidateDirect;                  CheckCandidate = CheckCandidateDirect;
1414          else CheckCandidate = CheckCandidateDirectno4v;          else CheckCandidate = CheckCandidateDirectno4v;
1415    
1416            (*CheckCandidate)(0, 0, 255, &k, Data);
1417    
1418    // skip decision
1419            if (*Data->iMinSAD - 2 * Data->lambda16 < (uint32_t)pMB->quant * SKIP_THRESH_B) {
1420                    //possible skip - checking chroma. everything copied from MC
1421                    //this is not full chroma compensation, only it's fullpel approximation. should work though
1422                    int sum, dx, dy, b_dx, b_dy;
1423    
1424                    sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1425                    dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1426    
1427                    sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1428                    dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1429    
1430                    sum = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;
1431                    b_dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1432    
1433                    sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;
1434                    b_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1435    
1436                    sum = sad8bi(pCur->u + 8*x + 8*y*(Data->iEdgedWidth/2),
1437                                            f_Ref->u + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1438                                            b_Ref->u + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1439                                            Data->iEdgedWidth/2);
1440                    sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1441                                            f_Ref->v + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1442                                            b_Ref->v + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1443                                            Data->iEdgedWidth/2);
1444    
1445                    if (sum < MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) {
1446                            pMB->mode = MODE_DIRECT_NONE_MV;
1447                            return *Data->iMinSAD;
1448                    }
1449            }
1450    
1451            skip_sad = *Data->iMinSAD;
1452    
1453  //  DIRECT MODE DELTA VECTOR SEARCH.  //  DIRECT MODE DELTA VECTOR SEARCH.
1454  //      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
1455    
# Line 1123  Line 1457 
1457                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1458                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1459    
1460          (*MainSearchPtr)(0, 0, &Data, 255);          (*MainSearchPtr)(0, 0, Data, 255);
1461    
1462          HalfpelRefine(&Data);          HalfpelRefine(Data);
1463    
1464          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 * 2; // one bit is needed to code direct mode
1465          *best_sad = iMinSAD;          *best_sad = *Data->iMinSAD;
1466    
1467          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1468                  pMB->mode = MODE_DIRECT;                  pMB->mode = MODE_DIRECT;
1469          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1470    
1471          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1472    
1473          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1474                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1475                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = ((Data->currentMV->x == 0)
1476                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1477                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          : pMB->mvs[k].x - Data->referencemv[k].x);
1478                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1479                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1480                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1481                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1482                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1483                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1484                          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];
1485                          break;                          break;
1486                  }                  }
1487          }          }
1488          return 0;//skip_sad;          return skip_sad;
1489  }  }
1490    
1491    
1492  static __inline void  static __inline void
1493  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const uint8_t * const f_Ref,
1494                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
# Line 1168  Line 1503 
1503                                  const uint32_t fcode,                                  const uint32_t fcode,
1504                                  const uint32_t bcode,                                  const uint32_t bcode,
1505                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1506                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1507                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1508                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1509                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1510                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1511                                    SearchData * const fData)
1512    
1513  {  {
 /* 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". */  
1514    
1515          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1516    
1517          int iDirection, i, j;          int iDirection, i, j;
1518          int32_t iMinSAD = 256*4096;          SearchData bData;
         VECTOR currentMV[3];  
         SearchData fData, bData;  
   
   
         fData.iMinSAD = bData.iMinSAD = &iMinSAD;  
1519    
1520          fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          *(bData.iMinSAD = fData->iMinSAD) = 4096*256;
1521          fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;          bData.Cur = fData->Cur;
1522          fData.currentMV = currentMV; bData.currentMV = currentMV + 1;          fData->iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;
1523          fData.iQuant = bData.iQuant = iQuant;          bData.currentMV = fData->currentMV + 1;
1524          fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;          bData.lambda16 = fData->lambda16;
1525            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1526    
1527            bData.bRef = fData->Ref = f_Ref + (x + y * iEdgedWidth) * 16;
1528            bData.bRefH = fData->RefH = f_RefH + (x + y * iEdgedWidth) * 16;
1529            bData.bRefV = fData->RefV = f_RefV + (x + y * iEdgedWidth) * 16;
1530            bData.bRefHV = fData->RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;
1531            bData.Ref = fData->bRef = b_Ref + (x + y * iEdgedWidth) * 16;
1532            bData.RefH = fData->bRefH = b_RefH + (x + y * iEdgedWidth) * 16;
1533            bData.RefV = fData->bRefV = b_RefV + (x + y * iEdgedWidth) * 16;
1534            bData.RefHV = fData->bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;
1535    
1536            bData.bpredMV = fData->predMV = *f_predMV;
1537            fData->bpredMV = bData.predMV = *b_predMV;
1538    
1539            fData->currentMV[0] = fData->currentMV[3]; //forward search stored it's vector here. backward stored it in the place it's needed
1540            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);
1541            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);
1542    
1543            if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1544            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dy;
1545            if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dx;
1546            if (fData->currentMV[0].y > fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1547    
1548            if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1549            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dy;
1550            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dx;
1551            if (fData->currentMV[1].y > bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1552    
1553            CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
         bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  
         bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;  
         bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;  
         bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;  
         bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;  
         bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;  
         bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;  
         bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;  
   
         bData.bpredMV = fData.predMV = *f_predMV;  
         fData.bpredMV = bData.predMV = *b_predMV;  
   
   
         currentMV[0] = pMB->mvs[0];  
         currentMV[1] = pMB->b_mvs[0];  
         get_range(&fData.min_dx, &fData.max_dx, &fData.min_dy, &fData.max_dy, x, y, 16, pParam->width, pParam->height, fcode);  
         get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode);  
   
         CheckCandidateInt(currentMV[0].x, currentMV[0].y, 255, &iDirection, &fData);  
1554    
1555  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)
1556    
1557          do {          do {
1558                  iDirection = 255;                  iDirection = 255;
1559                  // forward MV moves                  // forward MV moves
1560                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
1561    
1562                  CheckCandidateInt(i + 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1563                  CheckCandidateInt(i, j + 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1564                  CheckCandidateInt(i - 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1565                  CheckCandidateInt(i, j - 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
1566    
1567                  // backward MV moves                  // backward MV moves
1568                  i = currentMV[1].x; j = currentMV[1].y;                  i = fData->currentMV[1].x; j = fData->currentMV[1].y;
1569                  currentMV[2] = currentMV[0];                  fData->currentMV[2] = fData->currentMV[0];
1570    
1571                  CheckCandidateInt(i + 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1572                  CheckCandidateInt(i, j + 2, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1573                  CheckCandidateInt(i - 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
1574                  CheckCandidateInt(i, j - 2, 0, &iDirection, &bData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, &bData);
1575    
1576          } while (!(iDirection));          } while (!(iDirection));
1577    
 /* halfpel refinement. luckly we can use normal halfpel function for it */  
   
         if (MotionFlags & PMV_HALFPELREFINE16) {  
                 CheckCandidate = CheckCandidateInt;  
                 HalfpelRefine(&fData);  
                 currentMV[2] = currentMV[0];  
                 HalfpelRefine(&bData);  
         }  
   
1578  // two bits are needed to code interpolate mode. we treat the bits just like they were vector's  // two bits are needed to code interpolate mode. we treat the bits just like they were vector's
1579          iMinSAD +=  2 * lambda_vec16[iQuant];          *fData->iMinSAD +=  2 * fData->lambda16 * 2;
1580          if (iMinSAD < *best_sad) {  
1581                  *best_sad = iMinSAD;          if (*fData->iMinSAD < *best_sad) {
1582                  pMB->mvs[0] = currentMV[0];                  *best_sad = *fData->iMinSAD;
1583                  pMB->b_mvs[0] = currentMV[1];                  pMB->mvs[0] = fData->currentMV[0];
1584                    pMB->b_mvs[0] = fData->currentMV[1];
1585                  pMB->mode = MODE_INTERPOLATE;                  pMB->mode = MODE_INTERPOLATE;
1586    
1587                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;
# Line 1265  Line 1591 
1591          }          }
1592  }  }
1593    
1594    
1595  void  void
1596  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
1597                                           FRAMEINFO * const frame,                                           FRAMEINFO * const frame,
# Line 1293  Line 1620 
1620          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1621          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
1622    
1623    // some pre-inintialized data for the rest of the search
1624    
1625            SearchData Data;
1626            int32_t iMinSAD;
1627            VECTOR currentMV[3];
1628            Data.iEdgedWidth = pParam->edged_width;
1629            Data.currentMV = currentMV;
1630            Data.iMinSAD = &iMinSAD;
1631            Data.lambda16 = lambda_vec16[frame->quant];
1632    
1633          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
1634    
1635          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
# Line 1303  Line 1640 
1640                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;
1641                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;
1642    
1643  /* 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 */
1644                          if (b_mb->mode == MODE_NOT_CODED) {                          if ( (b_mb->mode == MODE_NOT_CODED) ) {
1645                                  pMB->mode = MODE_NOT_CODED;                                  pMB->mode = MODE_NOT_CODED;
1646                                  continue;                                  continue;
1647                          }                          }
1648    
1649                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
1650                            pMB->quant = frame->quant;
1651  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
1652          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
1653    
1654                          skip_sad = SearchDirect(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                          skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
1655                                                                          b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,
1656                                                                          &frame->image,                                                                          &frame->image,
1657                                                                          i, j,                                                                          i, j,
1658                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
1659                                                                          TRB, TRD,                                                                          TRB, TRD,
1660                                                                          pParam,                                                                          pParam,
1661                                                                          pMB, b_mb,                                                                          pMB, b_mb,
1662                                                                          &best_sad);                                                                          &best_sad,
1663                                                                            &Data);
1664    
                         if (!(frame->global_flags & XVID_HALFPEL)) best_sad = skip_sad = 256*4096;  
                         else  
1665                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1666    
1667  //                      best_sad = 256*4096; //uncomment to disable Directsearch.  //                      best_sad = 256*4096; //uncomment to disable Directsearch.
# Line 1334  Line 1671 
1671                          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,
1672                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1673                                                  frame->motion_flags,                                                  frame->motion_flags,
1674                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
1675                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
1676                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
1677    
1678                          // backward search                          // backward search
1679                          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,
1680                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1681                                                  frame->motion_flags,                                                  frame->motion_flags,
1682                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
1683                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
1684                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
1685    
1686                          // 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
1687    
# Line 1354  Line 1691 
1691                                                  i, j,                                                  i, j,
1692                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
1693                                                  frame->motion_flags,                                                  frame->motion_flags,
1694                                                  frame->quant, pParam,                                                  pParam,
1695                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
1696                                                  pMB, &best_sad);                                                  pMB, &best_sad,
1697                                                    &Data);
1698    
1699                          switch (pMB->mode) {                          switch (pMB->mode) {
1700                                  case MODE_FORWARD:                                  case MODE_FORWARD:
# Line 1389  Line 1727 
1727    
1728  /* Hinted ME starts here */  /* Hinted ME starts here */
1729    
1730  static __inline void  static void
1731  Search8hinted(  const SearchData * const OldData,  Search8hinted(  const SearchData * const OldData,
1732                                  const int x, const int y,                                  const int x, const int y,
1733                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1734                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1735                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1736                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1737                                  const int block)                          const int block,
1738                            SearchData * const Data)
1739  {  {
1740          SearchData Data;          int32_t temp_sad;
1741          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1742            Data->iMinSAD = OldData->iMinSAD + 1 + block;
1743          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          Data->currentMV = OldData->currentMV + 1 + block;
1744          Data.iMinSAD = OldData->iMinSAD + 1 + block;          Data->currentQMV = OldData->currentQMV + 1 + block;
1745          Data.currentMV = OldData->currentMV+1+block;          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1746          Data.iFcode = OldData->iFcode;  
1747          Data.iQuant = OldData->iQuant;          if(pParam->m_quarterpel) {
1748                    Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1749          Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));                  if (block != 0) *(Data->iMinSAD) += Data->lambda8 *
1750          Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));                                                                          d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1751          Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));                                                                                                  Data->currentQMV->y - Data->predQMV.y,
1752          Data.RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));                                                                                                  Data->iFcode);
1753          Data.iEdgedWidth = pParam->edged_width;                  CheckCandidate = CheckCandidate8Q;
1754          Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));          } else {
1755                    if (block != 0) *(Data->iMinSAD) += Data->lambda8 *
1756                                                                            d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1757                                                                                                    Data->currentMV->y - Data->predMV.y,
1758                                                                                                    Data->iFcode);
1759          CheckCandidate = CheckCandidate8;          CheckCandidate = CheckCandidate8;
1760            }
1761    
1762            Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));
1763            Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));
1764            Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1765            Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1766    
1767          if (block != 0)          Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
                 *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *  
                                                                 d_mv_bits(      Data.currentMV->x - Data.predMV.x,  
                                                                                         Data.currentMV->y - Data.predMV.y,  
                                                                                         Data.iFcode);  
1768    
1769            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1770                                    pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1771    
1772          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,          temp_sad = *(Data->iMinSAD); // store current MinSAD
                                 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); }  
1773    
1774          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1775                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1776                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1777    
1778          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1779    
1780            if(*(Data->iMinSAD) < temp_sad) {
1781                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1782                    Data->currentQMV->y = 2 * Data->currentMV->y;
1783            }
1784    
1785          if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);          if (MotionFlags & PMV_HALFPELREFINE8) {
1786                    temp_sad = *(Data->iMinSAD); // store current MinSAD
1787    
1788          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;                  HalfpelRefine(Data); // perform halfpel refine of current best vector
1789          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;  
1790          pMB->mvs[block] = *(Data.currentMV);                  if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1791          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                          Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1792                            Data->currentQMV->y = 2 * Data->currentMV->y;
1793                    }
1794  }  }
1795    
1796            if(pParam->m_quarterpel) {
1797                    if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1798                            (MotionFlags & PMV_QUARTERPELREFINE8)) {
1799                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1800                                    pParam->width, pParam->height, Data->iFcode, 0);
1801                            CheckCandidate = CheckCandidate8_qpel;
1802                            QuarterpelRefine(Data);
1803                    }
1804            pMB->pmvs[block].x = Data->currentQMV->x - Data->predQMV.x;
1805            pMB->pmvs[block].y = Data->currentQMV->y - Data->predQMV.y;
1806            } else {
1807                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1808                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1809            }
1810    
1811            pMB->mvs[block] = *(Data->currentMV);
1812            pMB->qmvs[block] = *(Data->currentQMV);
1813    
1814            pMB->sad8[block] =  4 * (*Data->iMinSAD);
1815    }
1816    
1817  static void  static void
1818  SearchPhinted ( const uint8_t * const pRef,  SearchPhinted ( const uint8_t * const pRef,
# Line 1455  Line 1824 
1824                                  const int y,                                  const int y,
1825                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1826                                  const uint32_t iQuant,                                  const uint32_t iQuant,
                                 const uint32_t iFcode,  
1827                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1828                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1829                                  int inter4v,                                  int inter4v,
1830                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
1831                                    SearchData * const Data)
1832  {  {
1833    
1834          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1835    
1836          int i;          int i, t;
         VECTOR currentMV[5];  
         int32_t iMinSAD[5];  
         int32_t temp[5];  
1837          MainSearchFunc * MainSearchPtr;          MainSearchFunc * MainSearchPtr;
         SearchData Data;  
   
         Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);  
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,  
                                 pParam->width, pParam->height, iFcode);  
1838    
1839          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1840          Data.iEdgedWidth = iEdgedWidth;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1841          Data.currentMV = currentMV;                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
1842          Data.iMinSAD = iMinSAD;  
1843          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data->Cur = pCur->y + (x + y * iEdgedWidth) * 16;
1844          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->Ref = pRef + (x + iEdgedWidth*y)*16;
1845          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + iEdgedWidth*y) * 16;
1846          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + iEdgedWidth*y) * 16;
1847          Data.temp = temp;          Data->RefHV = pRefHV + (x + iEdgedWidth*y) * 16;
1848          Data.iQuant = iQuant;          Data->lambda16 = lambda_vec16[iQuant];
1849          Data.iFcode = iFcode;          Data->lambda8 = lambda_vec8[iQuant];
1850    
1851          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
1852                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
1853                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
1854                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
1855                  Data.max_dy = EVEN(Data.max_dy);                  Data->max_dy = EVEN(Data->max_dy);
1856          }          }
1857    
1858          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;          for(i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
1859    
1860          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
1861    
1862          if (inter4v)          if(pParam->m_quarterpel) CheckCandidate = CheckCandidate16Q;
1863                  CheckCandidate = CheckCandidate16;          else
1864                    if (inter4v) CheckCandidate = CheckCandidate16;
1865          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
1866    
   
1867          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);
1868          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);
1869          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
1870          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;
1871          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;
1872          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;
1873    
1874          CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);          (*CheckCandidate)(pMB->mvs[0].x, pMB->mvs[0].y, 0, &t, Data);
1875    
1876          if (pMB->mode == MODE_INTER4V)          if (pMB->mode == MODE_INTER4V)
1877                  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
1878                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);
1879                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);
1880                          if (!(make_mask(pMB->mvs, i)))                          if (!(make_mask(pMB->mvs, i)))
1881                                  CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);                                  (*CheckCandidate)(pMB->mvs[i].x, pMB->mvs[i].y, 0, &t, Data);
1882                  }                  }
1883    
1884          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1526  Line 1887 
1887                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1888                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1889    
1890          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1891    
1892          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1893    
1894          if (inter4v)          for(i = 0; i < 5; i++) {
1895                  for(i = 0; i < 4; i++)                  Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1896                          Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                  Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1897            }
1898    
1899            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1900                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1901                                    pParam->width, pParam->height, Data->iFcode, 0);
1902                    CheckCandidate = CheckCandidate16_qpel;
1903                    QuarterpelRefine(Data);
1904            }
1905    
1906            if (inter4v) {
1907                    SearchData Data8;
1908                    Data8.iFcode = Data->iFcode;
1909                    Data8.lambda8 = Data->lambda8;
1910                    Data8.iEdgedWidth = Data->iEdgedWidth;
1911                    Data8.RefQ = Data->RefQ;
1912                    Search8hinted(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1913                    Search8hinted(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1914                    Search8hinted(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1915                    Search8hinted(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1916            }
1917    
1918          if (!(inter4v) ||          if (!(inter4v) ||
1919                  (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] +
1920                                                            Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1921  // INTER MODE  // INTER MODE
   
1922                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1923                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1924                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1925    
1926                    pMB->qmvs[0] = pMB->qmvs[1]
1927                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1928    
1929                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1930                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1931    
1932                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1933                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predQMV.x;
1934                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predQMV.y;
1935                    }
1936                    else {
1937                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1938                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1939                    }
1940          } else {          } else {
1941  // INTER4V MODE; all other things are already set in Search8hinted  // INTER4V MODE; all other things are already set in Search8hinted
1942                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1943                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3]
1944                                                    + Data->iMinSAD[4] + IMV16X16 * iQuant;
1945          }          }
1946    
1947  }  }
# Line 1568  Line 1959 
1959          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
1960    
1961          uint32_t x, y;          uint32_t x, y;
1962            uint8_t * qimage;
1963            int32_t temp[5], quant = current->quant;
1964            int32_t iMinSAD[5];
1965            VECTOR currentMV[5], currentQMV[5];
1966            SearchData Data;
1967            Data.iEdgedWidth = pParam->edged_width;
1968            Data.currentMV = currentMV;
1969            Data.currentQMV = currentQMV;
1970            Data.iMinSAD = iMinSAD;
1971            Data.temp = temp;
1972            Data.iFcode = current->fcode;
1973            Data.rounding = pParam->m_rounding_type;
1974    
1975            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
1976                    return; // allocate some mem for qpel interpolated blocks
1977                                      // somehow this is dirty since I think we shouldn't use malloc outside
1978                                      // encoder_create() - so please fix me!
1979    
1980            Data.RefQ = qimage;
1981    
1982          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
1983    
1984          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
1985                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
                         int32_t sad00;  
1986    
1987                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
1988    
1989  //intra mode is copied from the first pass. At least for the time being  //intra mode is copied from the first pass. At least for the time being
1990                          if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;                          if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;
1991    
1992    
1993                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
1994                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
1995                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant; }
1996                            else {
1997                                    if (pMB->dquant != NO_CHANGE) {
1998                                            quant += DQtab[pMB->dquant];
1999                                            if (quant > 31) quant = 31;
2000                                            else if (quant < 1) quant = 1;
2001                                    }
2002                                    pMB->quant = quant;
2003                            }
2004    
2005                          if (pMB->dquant == NO_CHANGE) //no skip otherwise, anyway                          SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
2006                                  sad00 = pMB->sad16                                                          y, current->motion_flags, pMB->quant,
2007                                          = sad16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
2008                                                                  pRef->y + (x + y * pParam->edged_width) * 16,                                                          &Data);
                                                                 pParam->edged_width, 256*4096 );  
                         else sad00 = 256*4096;  
2009    
2010                    }
2011            }
2012            free(qimage);
2013    }
2014    
2015  //initial skip decision  static __inline int
2016    MEanalyzeMB (   const uint8_t * const pRef,
2017                                    const uint8_t * const pCur,
2018                                    const int x,
2019                                    const int y,
2020                                    const MBParam * const pParam,
2021                                    const MACROBLOCK * const pMBs,
2022                                    MACROBLOCK * const pMB,
2023                                    SearchData * const Data)
2024    {
2025    
2026                          if ( (pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)          int i = 255, mask;
2027                                  && ( //(pMB->mode == MODE_NOT_CODED) ||          VECTOR pmv[3];
2028                                          (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant) )) ) {  
2029                                  if (sad00 < pMB->quant * INITIAL_SKIP_THRESH) {          *(Data->iMinSAD) = MV_MAX_ERROR;
2030                                          SkipMacroblockP(pMB, sad00);          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
2031                                          continue; } //skipped          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2032                                    pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
2033    
2034            Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
2035            Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
2036    
2037            CheckCandidate = CheckCandidate16no4vI;
2038    
2039            pmv[1].x = EVEN(pMB->mvs[0].x);
2040            pmv[1].y = EVEN(pMB->mvs[0].y);
2041            pmv[0].x = EVEN(Data->predMV.x);
2042            pmv[0].y = EVEN(Data->predMV.y);
2043            pmv[2].x = pmv[2].y = 0;
2044    
2045            CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, Data);
2046            if (!(mask = make_mask(pmv, 1)))
2047                    CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, Data);
2048            if (!(mask = make_mask(pmv, 2)))
2049                    CheckCandidate16no4vI(0, 0, mask, &i, Data);
2050    
2051            DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
2052    
2053            pMB->mvs[0] = *Data->currentMV;
2054    
2055            return *(Data->iMinSAD);
2056                          }                          }
                         else sad00 = 256*4096;  
2057    
2058                          if (pMB->mode == MODE_NOT_CODED)  #define INTRA_THRESH    1350
2059                                  SearchP(        pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,  #define INTER_THRESH    900
                                                         y, current->motion_flags, pMB->quant,  
                                                         current->fcode, pParam, pMBs, reference->mbs,  
                                                         current->global_flags & XVID_INTER4V, pMB);  
2060    
2061                          else  int
2062                                  SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,  MEanalysis(     const IMAGE * const pRef,
2063                                                          y, current->motion_flags, pMB->quant,                          const IMAGE * const pCurrent,
2064                                                          current->fcode, pParam, pMBs,                          MBParam * const pParam,
2065                                                          current->global_flags & XVID_INTER4V, pMB);                          MACROBLOCK * const pMBs,
2066                            const uint32_t iFcode)
2067    {
2068            uint32_t x, y, intra = 0;
2069            int sSAD = 0;
2070    
2071  /* final skip decision, a.k.a. "the vector you found, really that good?" */          VECTOR currentMV;
2072                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)          int32_t iMinSAD;
2073                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)          SearchData Data;
2074                                  SkipMacroblockP(pMB, sad00);          Data.iEdgedWidth = pParam->edged_width;
2075            Data.currentMV = &currentMV;
2076            Data.iMinSAD = &iMinSAD;
2077            Data.iFcode = iFcode;
2078    
2079            if (sadInit) (*sadInit) ();
2080    
2081            for (y = 1; y < pParam->mb_height-1; y++) {
2082                    for (x = 1; x < pParam->mb_width-1; x++) {
2083                            int sad, dev;
2084                            MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2085    
2086                            sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
2087                                                                    pParam, pMBs, pMB, &Data);
2088    
2089                            if (sad > INTRA_THRESH) {
2090                                    dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
2091                                                              pParam->edged_width);
2092                                    if (dev + INTRA_THRESH < sad) intra++;
2093                                    if (intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame
2094                                    }
2095                            sSAD += sad;
2096                    }
2097            }
2098            sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2099            if (sSAD > INTER_THRESH ) return 1; //P frame
2100            emms();
2101            return 0; // B frame
2102    
2103    }
2104    
2105    int
2106    FindFcode(      const MBParam * const pParam,
2107                            const FRAMEINFO * const current)
2108    {
2109            uint32_t x, y;
2110            int max = 0, min = 0, i;
2111    
2112            for (y = 0; y < pParam->mb_height; y++) {
2113                    for (x = 0; x < pParam->mb_width; x++) {
2114    
2115                            MACROBLOCK *pMB = &current->mbs[x + y * pParam->mb_width];
2116                            for(i = 0; i < (pMB->mode == MODE_INTER4V ? 4:1); i++) {
2117                                    if (pMB->mvs[i].x > max) max = pMB->mvs[i].x;
2118                                    if (pMB->mvs[i].y > max) max = pMB->mvs[i].y;
2119    
2120                                    if (pMB->mvs[i].x < min) min = pMB->mvs[i].x;
2121                                    if (pMB->mvs[i].y < min) min = pMB->mvs[i].y;
2122                  }                  }
2123          }          }
2124  }  }
2125    
2126            min = -min;
2127            max += 1;
2128            if (min > max) max = min;
2129            if (pParam->m_quarterpel) max *= 2;
2130    
2131            for (i = 1; (max > 32 << (i - 1)); i++);
2132            return i;
2133    }
2134    
2135    
2136    /* Global Motion Estimation, (C) 2002 by sysKin */
2137    /* calculate global translation from local (halfpel) motion field */
2138    
2139    static VECTOR
2140    GlobalMotionEst(const MACROBLOCK * const pMBs, const MBParam * const pParam, const uint32_t iFcode)
2141    {
2142    
2143            int count, bestcount = 0;
2144            int x, y;
2145            VECTOR gmc;
2146            int step, min_x, max_x, min_y, max_y;
2147            uint32_t mx, my;
2148    
2149            min_x = min_y = -32<<iFcode;
2150            max_x = max_y = 32<<iFcode;
2151    
2152            for (step = 32; step >= 2; step /= 2) {
2153                    bestcount = 0;
2154                    for (y = min_y; y <= max_y; y += step)
2155                            for (x = min_x ; x <= max_x; x += step) {
2156                                    count = 0;
2157                                    //for all macroblocks
2158                                    for (my = 1; my < pParam->mb_height-1; my++)
2159                                            for (mx = 1; mx < pParam->mb_width-1; mx++) {
2160                                                    const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2161                                                    VECTOR mv;
2162    
2163                                                    if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
2164                                                            continue;
2165    
2166                                                    mv = pMB->mvs[0];
2167                                                    if ( ABS(mv.x - x) <= step && ABS(mv.y - y) <= step )   /* GMC translation is always halfpel-res */
2168                                                            count++;
2169                                            }
2170                                    if (count >= bestcount) { bestcount = count; gmc.x = x; gmc.y = y; }
2171                            }
2172                    min_x = gmc.x - step;
2173                    max_x = gmc.x + step;
2174                    min_y = gmc.y - step;
2175                    max_y = gmc.y + step;
2176    
2177            }
2178            if (pParam->m_quarterpel) {
2179                    gmc.x *= 2;
2180                    gmc.y *= 2;     /* we store the halfpel value as pseudo-qpel to make comparison easier */
2181            }
2182    
2183            if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10)
2184                    gmc.x = gmc.y = 0; //no camara pan, no GMC
2185    
2186            return gmc;
2187    }

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

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