[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 606, Mon Oct 21 13:07:33 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);
         sad += sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);  
191    
192          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
193                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 149  Line 196 
196  }  }
197    
198  static void  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)) {
285                    *(data->iMinSAD) = sad;
286                    data->currentMV[0].x = x; data->currentMV[0].y = y;
287                    *dir = Direction; }
288    }
289    
290    
291    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  {  {
294          int32_t sad;          int32_t sad;
# 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    
758            pMB->qmvs[0].x = pMB->qmvs[1].x = pMB->qmvs[2].x = pMB->qmvs[3].x = 0;
759            pMB->qmvs[0].y = pMB->qmvs[1].y = pMB->qmvs[2].y = pMB->qmvs[3].y = 0;
760    
761          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;
762  }  }
763    
# Line 530  Line 778 
778    
779          uint32_t x, y;          uint32_t x, y;
780          uint32_t iIntra = 0;          uint32_t iIntra = 0;
781          int32_t InterBias;          int32_t InterBias, quant = current->quant;
782            uint8_t *qimage;
783    
784            // some pre-initialized thingies for SearchP
785            int32_t temp[5];
786            VECTOR currentMV[5];
787            VECTOR currentQMV[5];
788            int32_t iMinSAD[5];
789            SearchData Data;
790            Data.iEdgedWidth = pParam->edged_width;
791            Data.currentMV = currentMV;
792            Data.currentQMV = currentQMV;
793            Data.iMinSAD = iMinSAD;
794            Data.temp = temp;
795            Data.iFcode = current->fcode;
796            Data.rounding = pParam->m_rounding_type;
797    
798            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
799                    return 1; // allocate some mem for qpel interpolated blocks
800                                      // somehow this is dirty since I think we shouldn't use malloc outside
801                                      // encoder_create() - so please fix me!
802    
803          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
804    
# Line 545  Line 813 
813    
814                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
815                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
816                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant;
817                            } else {
818                                    if (pMB->dquant != NO_CHANGE) {
819                                            quant += DQtab[pMB->dquant];
820                                            if (quant > 31) quant = 31;
821                                            else if (quant < 1) quant = 1;
822                                    }
823                                    pMB->quant = quant;
824                            }
825    
826  //initial skip decision  //initial skip decision
827    
828                          if ((pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)                          if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * INITIAL_SKIP_THRESH)
829                                  && (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) ) {                                  if (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
                                 if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {  
830                                                  SkipMacroblockP(pMB, sad00);                                                  SkipMacroblockP(pMB, sad00);
831                                                  continue;                                                  continue;
832                                  }                                  }
                         } else sad00 = 256*4096; // skip not allowed - for final skip decision  
833    
834                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, qimage, pCurrent, x,
835                                                  y, current->motion_flags, pMB->quant,                                                  y, current->motion_flags, pMB->quant,
836                                                  current->fcode, pParam, pMBs, reference->mbs,                                                  &Data, pParam, pMBs, reference->mbs,
837                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
838    
839  /* 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?" */
840                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)                          if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * MAX_SAD00_FOR_SKIP
841                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)                                  && ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH) )
842                                  { SkipMacroblockP(pMB, sad00); continue; }                                  if (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
843                                            SkipMacroblockP(pMB, sad00);
844                                            continue;
845                                    }
846    
847  /* finally, intra decision */  /* finally, intra decision */
848    
# Line 582  Line 859 
859                                                    pParam->edged_width);                                                    pParam->edged_width);
860    
861                                  if (deviation < (pMB->sad16 - InterBias)) {                                  if (deviation < (pMB->sad16 - InterBias)) {
862                                          if (++iIntra >= iLimit) return 1;                                          if (++iIntra >= iLimit) { free(qimage); return 1; }
863                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
864                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
865                                                  pMB->mvs[3] = zeroMV;                                                  pMB->mvs[3] = zeroMV;
866                                            pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] =
867                                                            pMB->qmvs[3] = zeroMV;
868                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
869                                                  pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
870                                  }                                  }
871                          }                          }
872                  }                  }
873          }          }
874            free(qimage);
875          return 0;          return 0;
876  }  }
877    
# Line 601  Line 881 
881  static __inline int  static __inline int
882  make_mask(const VECTOR * const pmv, const int i)  make_mask(const VECTOR * const pmv, const int i)
883  {  {
884          int mask = 0xFF, j;          int mask = 255, j;
885          for (j = 0; j < i; j++) {          for (j = 0; j < i; j++) {
886                  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
887                  if (pmv[i].x == pmv[j].x) {                  if (pmv[i].x == pmv[j].x) {
# Line 625  Line 905 
905    
906          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour
907                  pmv[5].x = EVEN(pmv[3].x);                  pmv[5].x = EVEN(pmv[3].x);
908                  pmv[5].y = EVEN(pmv[3].y); }                  pmv[5].y = EVEN(pmv[3].y);
909          else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
910    
911          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
912          else pmv[3].x = pmv[3].y = 0;          else pmv[3].x = pmv[3].y = 0;
# Line 644  Line 924 
924    
925          if ((x != iWcount-1) && (y != iHcount-1)) {          if ((x != iWcount-1) && (y != iHcount-1)) {
926                  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
927                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y); }                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
928          else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
929  }  }
930    
931  static void  static void
# Line 653  Line 933 
933                  const uint8_t * const pRefH,                  const uint8_t * const pRefH,
934                  const uint8_t * const pRefV,                  const uint8_t * const pRefV,
935                  const uint8_t * const pRefHV,                  const uint8_t * const pRefHV,
936                    const uint8_t * const pRefQ,
937                  const IMAGE * const pCur,                  const IMAGE * const pCur,
938                  const int x,                  const int x,
939                  const int y,                  const int y,
940                  const uint32_t MotionFlags,                  const uint32_t MotionFlags,
941                  const uint32_t iQuant,                  const uint32_t iQuant,
942                  const uint32_t iFcode,                  SearchData * const Data,
943                  const MBParam * const pParam,                  const MBParam * const pParam,
944                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
945                  const MACROBLOCK * const prevMBs,                  const MACROBLOCK * const prevMBs,
# Line 666  Line 947 
947                  MACROBLOCK * const pMB)                  MACROBLOCK * const pMB)
948  {  {
949    
         const int32_t iEdgedWidth = pParam->edged_width;  
   
950          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
951          int32_t temp[5];          VECTOR pmv[7];
         VECTOR currentMV[5], pmv[7];  
         int32_t psad[4], iMinSAD[5];  
         MainSearchFunc * MainSearchPtr;  
         SearchData Data;  
952    
953          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)()
954          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,
955                                  pParam->width, pParam->height, iFcode);                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
956    
957          Data.predMV = pmv[0];          Data->predMV = pmv[0];
958          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
959          Data.iEdgedWidth = iEdgedWidth;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
960          Data.currentMV = currentMV;          Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;
961          Data.iMinSAD = iMinSAD;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
962          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
963          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
964          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->RefQ = pRefQ;
         Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;  
         Data.temp = temp;  
965    
966          Data.iQuant = iQuant;          Data->lambda16 = lambda_vec16[iQuant];
967          Data.iFcode = iFcode;          Data->lambda8 = lambda_vec8[iQuant];
968    
969          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
970                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
971                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
972                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
973                  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];  
974    
975          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
976    
977            for(i = 0;  i < 5; i++)
978                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
979    
980            if (pParam->m_quarterpel) {
981                    Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
982                    i = d_mv_bits(Data->predQMV.x, Data->predQMV.y, Data->iFcode);
983            } else i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);
984    
985            Data->iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;
986            Data->iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;
987            Data->iMinSAD[2] = pMB->sad8[1];
988            Data->iMinSAD[3] = pMB->sad8[2];
989            Data->iMinSAD[4] = pMB->sad8[3];
990    
991          if ((x == 0) && (y == 0)) threshA = 512;          if ((x == 0) && (y == 0)) threshA = 512;
992          else {          else {
993                  threshA = psad[0] + 20;                  threshA = Data->temp[0]; // that's when we keep this SAD atm
994                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
995                  if (threshA > 1024) threshA = 1024; }                  if (threshA > 1024) threshA = 1024; }
996    
997          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,
998                                          prevMBs + x + y * pParam->mb_width);                                          prevMBs + x + y * pParam->mb_width);
999    
1000            if (pParam->m_quarterpel) CheckCandidate = CheckCandidate16Q;
1001            else
1002          if (inter4v) CheckCandidate = CheckCandidate16;          if (inter4v) CheckCandidate = CheckCandidate16;
1003          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
1004    
# Line 727  Line 1006 
1006    
1007          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
1008                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1009                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  (*CheckCandidate)(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1010                  if (iMinSAD[0] < threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1011          }          }
1012    
1013          if ((iMinSAD[0] <= threshA) ||          if ((Data->iMinSAD[0] <= threshA) ||
1014                          (MVequal(currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
1015                          (iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {                          (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {
1016                  inter4v = 0;                  inter4v = 0;
1017                  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;  
                 }  
         }  
1018    
1019          if (MotionFlags & PMV_USESQUARES16)                  MainSearchFunc * MainSearchPtr;
1020                  MainSearchPtr = SquareSearch;                  if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
1021          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
                 MainSearchPtr = AdvDiamondSearch;  
1022                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1023    
1024          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, iDirection);                  (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1025    
1026  /* extended search, diamond starting in 0,0 and in prediction.  /* extended search, diamond starting in 0,0 and in prediction.
1027          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 1029 
1029    
1030          if (MotionFlags & PMV_EXTSEARCH16) {          if (MotionFlags & PMV_EXTSEARCH16) {
1031                  int32_t bSAD;                  int32_t bSAD;
1032                  VECTOR startMV = Data.predMV, backupMV = currentMV[0];                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
1033                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?
1034                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);
1035                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1036                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1037    
1038                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1039                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1040                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1041                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1042                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1043                  }                  }
1044    
1045                  backupMV = currentMV[0];                          backupMV = Data->currentMV[0];
1046                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;
1047                  else startMV.x = startMV.y = 0;                  else startMV.x = startMV.y = 0;
1048                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1049                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1050    
1051                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1052                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1053                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1054                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1055                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1056                            }
1057                  }                  }
1058          }          }
1059    
1060  PMVfast16_Terminate_with_Refine:          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1061    
1062            for(i = 0; i < 5; i++) {
1063                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1064                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1065            }
1066    
1067          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1068    
1069  PMVfast16_Terminate_without_Refine:                  CheckCandidate = CheckCandidate16_qpel;
1070                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1071                                    pParam->width, pParam->height, Data->iFcode, 0);
1072    
1073          if (inter4v)                  QuarterpelRefine(Data);
1074                  for(i = 0; i < 4; i++)          }
1075                          Search8(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);  
1076            if (inter4v) {
1077                    SearchData Data8;
1078                    Data8.iFcode = Data->iFcode;
1079                    Data8.lambda8 = Data->lambda8;
1080                    Data8.iEdgedWidth = Data->iEdgedWidth;
1081                    Data8.RefQ = Data->RefQ;
1082                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1083                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1084                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1085                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1086            }
1087    
1088          if (!(inter4v) ||          if (!(inter4v) ||
1089                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
1090                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1091  // INTER MODE  // INTER MODE
1092                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1093                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1094                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1095    
1096                    pMB->qmvs[0] = pMB->qmvs[1]
1097                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1098    
1099                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1100                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1101    
1102                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1103                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predQMV.x;
1104                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predQMV.y;
1105                    }
1106                    else {
1107                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1108                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1109                    }
1110          } else {          } else {
1111  // INTER4V MODE; all other things are already set in Search8  // INTER4V MODE; all other things are already set in Search8
1112                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1113                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1114                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1115          }          }
   
1116  }  }
1117    
1118  static void  static void
# Line 820  Line 1122 
1122                  const MBParam * const pParam,                  const MBParam * const pParam,
1123                  MACROBLOCK * const pMB,                  MACROBLOCK * const pMB,
1124                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
1125                  const int block)                  const int block,
1126                    SearchData * const Data)
1127  {  {
1128          SearchData Data;          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1129            Data->currentMV = OldData->currentMV + 1 + block;
1130          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          Data->currentQMV = OldData->currentQMV + 1 + block;
1131          Data.iMinSAD = OldData->iMinSAD + 1 + block;  
1132          Data.currentMV = OldData->currentMV+1+block;          if(pParam->m_quarterpel) {
1133          Data.iFcode = OldData->iFcode;                  Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1134          Data.iQuant = OldData->iQuant;                  if (block != 0) *(Data->iMinSAD) += Data->lambda8 *
1135                                                                            d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1136          if (block != 0)                                                                                                  Data->currentQMV->y - Data->predQMV.y,
1137                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *                                                                                                  Data->iFcode);
1138                                                                  d_mv_bits(      Data.currentMV->x - Data.predMV.x,                  CheckCandidate = CheckCandidate8Q;
1139                                                                                          Data.currentMV->y - Data.predMV.y,          } else {
1140                                                                                          Data.iFcode);                  Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1141                    if (block != 0) *(Data->iMinSAD) += Data->lambda8 *
1142                                                                            d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1143                                                                                                    Data->currentMV->y - Data->predMV.y,
1144                                                                                                    Data->iFcode);
1145                    CheckCandidate = CheckCandidate8;
1146            }
1147    
1148          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
1149    
1150                  Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));
1151                  Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));
1152                  Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1153                  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));  
1154    
1155                  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);  
1156    
1157                  CheckCandidate = CheckCandidate8;                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1158                                    pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1159    
1160                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & PMV_EXTSEARCH8) {
1161                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1162    
1163                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1164                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1165                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1166                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1167    
1168                          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);     }                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1169    
1170                            if(*(Data->iMinSAD) < temp_sad) {
1171                                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1172                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1173                            }
1174                    }
1175    
1176                    if (MotionFlags & PMV_HALFPELREFINE8) {
1177                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1178    
1179                            HalfpelRefine(Data); // perform halfpel refine of current best vector
1180    
1181                            if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1182                                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1183                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1184                            }
1185                    }
1186    
1187                    if(pParam->m_quarterpel) {
1188                            if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1189                                    (MotionFlags & PMV_QUARTERPELREFINE8)) {
1190                            CheckCandidate = CheckCandidate8_qpel;
1191                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1192                                    pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1193                            QuarterpelRefine(Data);
1194                            }
1195                    }
1196            }
1197    
1198                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);          if(pParam->m_quarterpel) {
1199                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predQMV.x;
1200                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predQMV.y;
1201            }
1202            else {
1203                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1204                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1205          }          }
1206    
1207          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;          pMB->mvs[block] = *(Data->currentMV);
1208          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;          pMB->qmvs[block] = *(Data->currentQMV);
1209          pMB->mvs[block] = *(Data.currentMV);  
1210          pMB->sad8[block] =  4 * (*(Data.iMinSAD));          pMB->sad8[block] =  4 * (*Data->iMinSAD);
1211  }  }
1212    
1213  /* B-frames code starts here */  /* B-frames code starts here */
# Line 896  Line 1235 
1235          pmv[2] = ChoosePred(pMB, mode_curr);          pmv[2] = ChoosePred(pMB, mode_curr);
1236          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);
1237    
         pmv[3].x = pmv[3].y = 0;  
1238          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour
1239                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);
1240                  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);
1241            } else pmv[3].x = pmv[3].y = 0;
1242    
1243          if (y != 0) {          if (y != 0) {
1244                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);
# Line 929  Line 1268 
1268                          const IMAGE * const pCur,                          const IMAGE * const pCur,
1269                          const int x, const int y,                          const int x, const int y,
1270                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
1271                          const uint32_t iFcode,                          const uint32_t iFcode,
1272                          const MBParam * const pParam,                          const MBParam * const pParam,
1273                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
1274                          const VECTOR * const predMV,                          const VECTOR * const predMV,
1275                          int32_t * const best_sad,                          int32_t * const best_sad,
1276                          const int32_t mode_current)                          const int32_t mode_current,
1277                            SearchData * const Data)
1278  {  {
1279    
1280          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1281    
1282          int i, iDirection, mask;          int i, iDirection, mask;
1283          VECTOR currentMV, pmv[7];          VECTOR pmv[7];
1284          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1285          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
1286          SearchData Data;          Data->iFcode = iFcode;
   
         Data.iMinSAD = &iMinSAD;  
         Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
         Data.iEdgedWidth = iEdgedWidth;  
         Data.currentMV = &currentMV;  
         Data.iMinSAD = &iMinSAD;  
         Data.Ref = pRef + (x + y * iEdgedWidth) * 16;  
         Data.RefH = pRefH + (x + y * iEdgedWidth) * 16;  
         Data.RefV = pRefV + (x + y * iEdgedWidth) * 16;  
         Data.RefHV = pRefHV + (x + y * iEdgedWidth) * 16;  
   
         Data.iQuant = iQuant;  
         Data.iFcode = iFcode;  
         Data.predMV = *predMV;  
1287    
1288          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,          Data->Ref = pRef + (x + y * iEdgedWidth) * 16;
1289                                  pParam->width, pParam->height, iFcode);          Data->RefH = pRefH + (x + y * iEdgedWidth) * 16;
1290            Data->RefV = pRefV + (x + y * iEdgedWidth) * 16;
1291            Data->RefHV = pRefHV + (x + y * iEdgedWidth) * 16;
1292    
1293          if (!(MotionFlags & PMV_HALFPEL16)) {          Data->predMV = *predMV;
                 Data.min_dx = EVEN(Data.min_dx);  
                 Data.max_dx = EVEN(Data.max_dx);  
                 Data.min_dy = EVEN(Data.min_dy);  
                 Data.max_dy = EVEN(Data.max_dy); } // no-halpel and b-frames. do we need it?  
1294    
1295            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1296                                    pParam->width, pParam->height, iFcode, pParam->m_quarterpel);
1297    
1298          pmv[0] = Data.predMV;          pmv[0] = Data->predMV;
1299          PreparePredictionsBF(pmv, x, y, pParam->mb_width,          PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
                                         pMB, mode_current);  
1300    
1301          currentMV.x = currentMV.y = 0;          Data->currentMV->x = Data->currentMV->y = 0;
1302    
1303          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1304    
1305  // main loop. checking all predictions  // main loop. checking all predictions
1306          for (i = 0; i < 8; i++) {          for (i = 0; i < 8; i++) {
1307                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1308                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1309          }          }
1310    
1311          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 990  Line 1314 
1314                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1315                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1316    
1317          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1318    
1319          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          HalfpelRefine(Data);
1320    
1321  // three bits are needed to code backward mode. four for forward  // three bits are needed to code backward mode. four for forward
1322  // we treat the bits just like they were vector's  // we treat the bits just like they were vector's
1323          if (mode_current == MODE_FORWARD) iMinSAD +=  4 * lambda_vec16[iQuant];          if (mode_current == MODE_FORWARD) *Data->iMinSAD +=  4 * Data->lambda16 * 2;
1324          else iMinSAD +=  3 * lambda_vec16[iQuant];          else *Data->iMinSAD +=  3 * Data->lambda16 * 2;
   
1325    
1326          if (iMinSAD < *best_sad) {          if (*Data->iMinSAD < *best_sad) {
1327                  *best_sad = iMinSAD;                  *best_sad = *Data->iMinSAD;
1328                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1329                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1330                  pMB->pmvs[0].y = currentMV.y - predMV->y;                  pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1331                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = *(Data->currentMV+2) = *Data->currentMV;
1332                  else pMB->b_mvs[0] = currentMV;                  else pMB->b_mvs[0] = *(Data->currentMV+1) = *Data->currentMV; //we store currmv for interpolate search
1333          }          }
1334    
1335  }  }
1336    
1337  static int32_t  static int32_t
1338  SearchDirect(const uint8_t * const f_Ref,  SearchDirect(const IMAGE * const f_Ref,
1339                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1340                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
1341                                  const uint8_t * const f_RefHV,                                  const uint8_t * const f_RefHV,
1342                                  const uint8_t * const b_Ref,                                  const IMAGE * const b_Ref,
1343                                  const uint8_t * const b_RefH,                                  const uint8_t * const b_RefH,
1344                                  const uint8_t * const b_RefV,                                  const uint8_t * const b_RefV,
1345                                  const uint8_t * const b_RefHV,                                  const uint8_t * const b_RefHV,
1346                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1347                                  const int x, const int y,                                  const int x, const int y,
1348                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1349                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1350                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1351                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1352                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1353                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1354                                    SearchData * const Data)
1355    
1356  {  {
1357          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
         int32_t iMinSAD = 0, skip_sad;  
1358          int k;          int k;
1359          VECTOR currentMV;  
1360          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
         SearchData Data;  
1361    
1362          Data.iMinSAD = &iMinSAD;          *Data->iMinSAD = 256*4096;
1363          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;  
1364    
1365          Data.Ref= f_Ref + (x + iEdgedWidth*y) * 16;          Data->Ref = f_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1366          Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;          Data->RefH = f_RefH + (x + Data->iEdgedWidth*y) * 16;
1367          Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;          Data->RefV = f_RefV + (x + Data->iEdgedWidth*y) * 16;
1368          Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = f_RefHV + (x + Data->iEdgedWidth*y) * 16;
1369          Data.bRef = b_Ref + (x + iEdgedWidth*y) * 16;          Data->bRef = b_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1370          Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;          Data->bRefH = b_RefH + (x + Data->iEdgedWidth*y) * 16;
1371          Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;          Data->bRefV = b_RefV + (x + Data->iEdgedWidth*y) * 16;
1372          Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;          Data->bRefHV = b_RefHV + (x + Data->iEdgedWidth*y) * 16;
1373  /*  
1374  //What we do here is a complicated version of CheckCandidateDirect(0,0);          Data->max_dx = 2 * pParam->width - 2 * (x) * 16;
1375  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;
1376            Data->min_dx = -(2 * 16 + 2 * (x) * 16);
1377  */          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);  
1378    
1379          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1380                  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);
1381                  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;
1382                  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);
1383                  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; }  
1384    
1385                    if ( ( pMB->b_mvs[k].x > Data->max_dx ) || ( pMB->b_mvs[k].x < Data->min_dx )
1386                            || ( pMB->b_mvs[k].y > Data->max_dy ) || ( pMB->b_mvs[k].y < Data->min_dy )) {
1387    
1388                            *best_sad = 256*4096; // in that case, we won't use direct mode
1389                            pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
1390                            pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;
1391                            return 0;
1392                    }
1393          if (b_mb->mode != MODE_INTER4V) {          if (b_mb->mode != MODE_INTER4V) {
1394                  iMinSAD = sad16bi(Data.Cur,                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1395                                                  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];
1396                                                                  x, y, 16, &pMB->mvs[0], iEdgedWidth),                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1397                                                  get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1398                                                                  x, y, 16, &pMB->b_mvs[0], iEdgedWidth), iEdgedWidth);                          break;
1399                    }
                 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);  
1400          }          }
1401    
 // 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;  
1402          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1403                  CheckCandidate = CheckCandidateDirect;                  CheckCandidate = CheckCandidateDirect;
1404          else CheckCandidate = CheckCandidateDirectno4v;          else CheckCandidate = CheckCandidateDirectno4v;
1405    
1406            (*CheckCandidate)(0, 0, 255, &k, Data);
1407    
1408    // skip decision
1409            if (*Data->iMinSAD - 2 * Data->lambda16 < (uint32_t)pMB->quant * SKIP_THRESH_B) {
1410                    //possible skip - checking chroma. everything copied from MC
1411                    //this is not full chroma compensation, only it's fullpel approximation. should work though
1412                    int sum, dx, dy, b_dx, b_dy;
1413    
1414                    sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1415                    dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1416    
1417                    sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1418                    dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1419    
1420                    sum = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;
1421                    b_dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1422    
1423                    sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;
1424                    b_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1425    
1426                    sum = sad8bi(pCur->u + 8*x + 8*y*(Data->iEdgedWidth/2),
1427                                            f_Ref->u + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1428                                            b_Ref->u + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1429                                            Data->iEdgedWidth/2);
1430                    sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1431                                            f_Ref->v + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1432                                            b_Ref->v + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1433                                            Data->iEdgedWidth/2);
1434    
1435                    if (sum < MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) {
1436                            pMB->mode = MODE_DIRECT_NONE_MV;
1437                            return *Data->iMinSAD;
1438                    }
1439            }
1440    
1441            skip_sad = *Data->iMinSAD;
1442    
1443  //  DIRECT MODE DELTA VECTOR SEARCH.  //  DIRECT MODE DELTA VECTOR SEARCH.
1444  //      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
1445    
# Line 1123  Line 1447 
1447                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1448                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1449    
1450          (*MainSearchPtr)(0, 0, &Data, 255);          (*MainSearchPtr)(0, 0, Data, 255);
1451    
1452          HalfpelRefine(&Data);          HalfpelRefine(Data);
1453    
1454          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
1455          *best_sad = iMinSAD;          *best_sad = *Data->iMinSAD;
1456    
1457          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1458                  pMB->mode = MODE_DIRECT;                  pMB->mode = MODE_DIRECT;
1459          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1460    
1461          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1462    
1463          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1464                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1465                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = ((Data->currentMV->x == 0)
1466                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1467                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          : pMB->mvs[k].x - Data->referencemv[k].x);
1468                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1469                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1470                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1471                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1472                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1473                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1474                          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];
1475                          break;                          break;
1476                  }                  }
1477          }          }
1478          return 0;//skip_sad;          return skip_sad;
1479  }  }
1480    
1481    
1482  static __inline void  static __inline void
1483  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const uint8_t * const f_Ref,
1484                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
# Line 1168  Line 1493 
1493                                  const uint32_t fcode,                                  const uint32_t fcode,
1494                                  const uint32_t bcode,                                  const uint32_t bcode,
1495                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1496                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1497                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1498                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1499                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1500                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1501                                    SearchData * const fData)
1502    
1503  {  {
 /* 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". */  
1504    
1505          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1506    
1507          int iDirection, i, j;          int iDirection, i, j;
1508          int32_t iMinSAD = 256*4096;          SearchData bData;
         VECTOR currentMV[3];  
         SearchData fData, bData;  
   
   
         fData.iMinSAD = bData.iMinSAD = &iMinSAD;  
   
         fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
         fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;  
         fData.currentMV = currentMV; bData.currentMV = currentMV + 1;  
         fData.iQuant = bData.iQuant = iQuant;  
         fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;  
   
   
         bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  
         bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;  
         bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;  
         bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;  
         bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;  
         bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;  
         bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;  
         bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;  
   
         bData.bpredMV = fData.predMV = *f_predMV;  
         fData.bpredMV = bData.predMV = *b_predMV;  
1509    
1510            *(bData.iMinSAD = fData->iMinSAD) = 4096*256;
1511            bData.Cur = fData->Cur;
1512            fData->iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;
1513            bData.currentMV = fData->currentMV + 1;
1514            bData.lambda16 = fData->lambda16;
1515            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1516    
1517            bData.bRef = fData->Ref = f_Ref + (x + y * iEdgedWidth) * 16;
1518            bData.bRefH = fData->RefH = f_RefH + (x + y * iEdgedWidth) * 16;
1519            bData.bRefV = fData->RefV = f_RefV + (x + y * iEdgedWidth) * 16;
1520            bData.bRefHV = fData->RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;
1521            bData.Ref = fData->bRef = b_Ref + (x + y * iEdgedWidth) * 16;
1522            bData.RefH = fData->bRefH = b_RefH + (x + y * iEdgedWidth) * 16;
1523            bData.RefV = fData->bRefV = b_RefV + (x + y * iEdgedWidth) * 16;
1524            bData.RefHV = fData->bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;
1525    
1526            bData.bpredMV = fData->predMV = *f_predMV;
1527            fData->bpredMV = bData.predMV = *b_predMV;
1528    
1529            fData->currentMV[0] = fData->currentMV[3]; //forward search stored it's vector here. backward stored it in the place it's needed
1530            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);
1531            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);
1532    
1533            if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1534            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dy;
1535            if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dx;
1536            if (fData->currentMV[0].y > fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1537    
1538            if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1539            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dy;
1540            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dx;
1541            if (fData->currentMV[1].y > bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1542    
1543          currentMV[0] = pMB->mvs[0];          CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
         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);  
1544    
1545  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)
1546    
1547          do {          do {
1548                  iDirection = 255;                  iDirection = 255;
1549                  // forward MV moves                  // forward MV moves
1550                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
1551    
1552                  CheckCandidateInt(i + 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1553                  CheckCandidateInt(i, j + 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1554                  CheckCandidateInt(i - 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1555                  CheckCandidateInt(i, j - 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
1556    
1557                  // backward MV moves                  // backward MV moves
1558                  i = currentMV[1].x; j = currentMV[1].y;                  i = fData->currentMV[1].x; j = fData->currentMV[1].y;
1559                  currentMV[2] = currentMV[0];                  fData->currentMV[2] = fData->currentMV[0];
1560    
1561                  CheckCandidateInt(i + 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1562                  CheckCandidateInt(i, j + 2, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1563                  CheckCandidateInt(i - 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
1564                  CheckCandidateInt(i, j - 2, 0, &iDirection, &bData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, &bData);
1565    
1566          } while (!(iDirection));          } while (!(iDirection));
1567    
 /* 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);  
         }  
   
1568  // 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
1569          iMinSAD +=  2 * lambda_vec16[iQuant];          *fData->iMinSAD +=  2 * fData->lambda16 * 2;
1570          if (iMinSAD < *best_sad) {  
1571                  *best_sad = iMinSAD;          if (*fData->iMinSAD < *best_sad) {
1572                  pMB->mvs[0] = currentMV[0];                  *best_sad = *fData->iMinSAD;
1573                  pMB->b_mvs[0] = currentMV[1];                  pMB->mvs[0] = fData->currentMV[0];
1574                    pMB->b_mvs[0] = fData->currentMV[1];
1575                  pMB->mode = MODE_INTERPOLATE;                  pMB->mode = MODE_INTERPOLATE;
1576    
1577                  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 1581 
1581          }          }
1582  }  }
1583    
1584    
1585  void  void
1586  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
1587                                           FRAMEINFO * const frame,                                           FRAMEINFO * const frame,
# Line 1293  Line 1610 
1610          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1611          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
1612    
1613    // some pre-inintialized data for the rest of the search
1614    
1615            SearchData Data;
1616            int32_t iMinSAD;
1617            VECTOR currentMV[3];
1618            Data.iEdgedWidth = pParam->edged_width;
1619            Data.currentMV = currentMV;
1620            Data.iMinSAD = &iMinSAD;
1621            Data.lambda16 = lambda_vec16[frame->quant];
1622    
1623          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
1624    
1625          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
# Line 1309  Line 1636 
1636                                  continue;                                  continue;
1637                          }                          }
1638    
1639                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
1640                            pMB->quant = frame->quant;
1641  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
1642          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
1643    
1644                          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,
1645                                                                          b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,
1646                                                                          &frame->image,                                                                          &frame->image,
1647                                                                          i, j,                                                                          i, j,
1648                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
1649                                                                          TRB, TRD,                                                                          TRB, TRD,
1650                                                                          pParam,                                                                          pParam,
1651                                                                          pMB, b_mb,                                                                          pMB, b_mb,
1652                                                                          &best_sad);                                                                          &best_sad,
1653                                                                            &Data);
1654    
                         if (!(frame->global_flags & XVID_HALFPEL)) best_sad = skip_sad = 256*4096;  
                         else  
1655                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1656    
1657  //                      best_sad = 256*4096; //uncomment to disable Directsearch.  //                      best_sad = 256*4096; //uncomment to disable Directsearch.
# Line 1334  Line 1661 
1661                          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,
1662                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1663                                                  frame->motion_flags,                                                  frame->motion_flags,
1664                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
1665                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
1666                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
1667    
1668                          // backward search                          // backward search
1669                          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,
1670                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1671                                                  frame->motion_flags,                                                  frame->motion_flags,
1672                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
1673                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
1674                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
1675    
1676                          // 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
1677    
# Line 1354  Line 1681 
1681                                                  i, j,                                                  i, j,
1682                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
1683                                                  frame->motion_flags,                                                  frame->motion_flags,
1684                                                  frame->quant, pParam,                                                  pParam,
1685                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
1686                                                  pMB, &best_sad);                                                  pMB, &best_sad,
1687                                                    &Data);
1688    
1689                          switch (pMB->mode) {                          switch (pMB->mode) {
1690                                  case MODE_FORWARD:                                  case MODE_FORWARD:
# Line 1389  Line 1717 
1717    
1718  /* Hinted ME starts here */  /* Hinted ME starts here */
1719    
1720  static __inline void  static void
1721  Search8hinted(  const SearchData * const OldData,  Search8hinted(  const SearchData * const OldData,
1722                                  const int x, const int y,                                  const int x, const int y,
1723                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1724                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1725                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1726                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1727                                  const int block)                          const int block,
1728                            SearchData * const Data)
1729  {  {
1730          SearchData Data;          int32_t temp_sad;
1731          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1732            Data->iMinSAD = OldData->iMinSAD + 1 + block;
1733          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          Data->currentMV = OldData->currentMV + 1 + block;
1734          Data.iMinSAD = OldData->iMinSAD + 1 + block;          Data->currentQMV = OldData->currentQMV + 1 + block;
1735          Data.currentMV = OldData->currentMV+1+block;          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1736          Data.iFcode = OldData->iFcode;  
1737          Data.iQuant = OldData->iQuant;          if(pParam->m_quarterpel) {
1738                    Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1739          Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));                  if (block != 0) *(Data->iMinSAD) += Data->lambda8 *
1740          Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));                                                                          d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1741          Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));                                                                                                  Data->currentQMV->y - Data->predQMV.y,
1742          Data.RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));                                                                                                  Data->iFcode);
1743          Data.iEdgedWidth = pParam->edged_width;                  CheckCandidate = CheckCandidate8Q;
1744          Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));          } else {
1745                    if (block != 0) *(Data->iMinSAD) += Data->lambda8 *
1746                                                                            d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1747                                                                                                    Data->currentMV->y - Data->predMV.y,
1748                                                                                                    Data->iFcode);
1749          CheckCandidate = CheckCandidate8;          CheckCandidate = CheckCandidate8;
1750            }
1751    
1752            Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));
1753            Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));
1754            Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1755            Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1756    
1757          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);  
1758    
1759            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1760                                    pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1761    
1762          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); }  
1763    
1764          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1765                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1766                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1767    
1768          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1769    
1770          if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);          if(*(Data->iMinSAD) < temp_sad) {
1771                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1772                    Data->currentQMV->y = 2 * Data->currentMV->y;
1773            }
1774    
1775            if (MotionFlags & PMV_HALFPELREFINE8) {
1776                    temp_sad = *(Data->iMinSAD); // store current MinSAD
1777    
1778          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;                  HalfpelRefine(Data); // perform halfpel refine of current best vector
1779          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;  
1780          pMB->mvs[block] = *(Data.currentMV);                  if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1781          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                          Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1782                            Data->currentQMV->y = 2 * Data->currentMV->y;
1783                    }
1784  }  }
1785    
1786            if(pParam->m_quarterpel) {
1787                    if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1788                            (MotionFlags & PMV_QUARTERPELREFINE8)) {
1789                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1790                                    pParam->width, pParam->height, Data->iFcode, 0);
1791                            CheckCandidate = CheckCandidate8_qpel;
1792                            QuarterpelRefine(Data);
1793                    }
1794            pMB->pmvs[block].x = Data->currentQMV->x - Data->predQMV.x;
1795            pMB->pmvs[block].y = Data->currentQMV->y - Data->predQMV.y;
1796            } else {
1797                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1798                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1799            }
1800    
1801            pMB->mvs[block] = *(Data->currentMV);
1802            pMB->qmvs[block] = *(Data->currentQMV);
1803    
1804            pMB->sad8[block] =  4 * (*Data->iMinSAD);
1805    }
1806    
1807  static void  static void
1808  SearchPhinted ( const uint8_t * const pRef,  SearchPhinted ( const uint8_t * const pRef,
# Line 1455  Line 1814 
1814                                  const int y,                                  const int y,
1815                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1816                                  const uint32_t iQuant,                                  const uint32_t iQuant,
                                 const uint32_t iFcode,  
1817                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1818                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1819                                  int inter4v,                                  int inter4v,
1820                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
1821                                    SearchData * const Data)
1822  {  {
1823    
1824          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1825    
1826          int i;          int i, t;
         VECTOR currentMV[5];  
         int32_t iMinSAD[5];  
         int32_t temp[5];  
1827          MainSearchFunc * MainSearchPtr;          MainSearchFunc * MainSearchPtr;
         SearchData Data;  
1828    
1829          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1830          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,
1831                                  pParam->width, pParam->height, iFcode);                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
1832    
1833          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->Cur = pCur->y + (x + y * iEdgedWidth) * 16;
1834          Data.iEdgedWidth = iEdgedWidth;          Data->Ref = pRef + (x + iEdgedWidth*y)*16;
1835          Data.currentMV = currentMV;          Data->RefH = pRefH + (x + iEdgedWidth*y) * 16;
1836          Data.iMinSAD = iMinSAD;          Data->RefV = pRefV + (x + iEdgedWidth*y) * 16;
1837          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data->RefHV = pRefHV + (x + iEdgedWidth*y) * 16;
1838          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->lambda16 = lambda_vec16[iQuant];
1839          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->lambda8 = lambda_vec8[iQuant];
         Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;  
         Data.temp = temp;  
         Data.iQuant = iQuant;  
         Data.iFcode = iFcode;  
1840    
1841          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
1842                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
1843                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
1844                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
1845                  Data.max_dy = EVEN(Data.max_dy);                  Data->max_dy = EVEN(Data->max_dy);
1846          }          }
1847    
1848          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;          for(i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
1849    
1850          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
1851    
1852          if (inter4v)          if(pParam->m_quarterpel) CheckCandidate = CheckCandidate16Q;
1853                  CheckCandidate = CheckCandidate16;          else
1854                    if (inter4v) CheckCandidate = CheckCandidate16;
1855          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
1856    
   
1857          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);
1858          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);
1859          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
1860          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;
1861          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;
1862          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;
1863    
1864          CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);          (*CheckCandidate)(pMB->mvs[0].x, pMB->mvs[0].y, 0, &t, Data);
1865    
1866          if (pMB->mode == MODE_INTER4V)          if (pMB->mode == MODE_INTER4V)
1867                  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
1868                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);
1869                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);
1870                          if (!(make_mask(pMB->mvs, i)))                          if (!(make_mask(pMB->mvs, i)))
1871                                  CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);                                  (*CheckCandidate)(pMB->mvs[i].x, pMB->mvs[i].y, 0, &t, Data);
1872                  }                  }
1873    
1874          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1526  Line 1877 
1877                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1878                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1879    
1880          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1881    
1882          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1883    
1884          if (inter4v)          for(i = 0; i < 5; i++) {
1885                  for(i = 0; i < 4; i++)                  Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1886                          Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                  Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1887            }
1888    
1889            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1890                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1891                                    pParam->width, pParam->height, Data->iFcode, 0);
1892                    CheckCandidate = CheckCandidate16_qpel;
1893                    QuarterpelRefine(Data);
1894            }
1895    
1896            if (inter4v) {
1897                    SearchData Data8;
1898                    Data8.iFcode = Data->iFcode;
1899                    Data8.lambda8 = Data->lambda8;
1900                    Data8.iEdgedWidth = Data->iEdgedWidth;
1901                    Data8.RefQ = Data->RefQ;
1902                    Search8hinted(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1903                    Search8hinted(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1904                    Search8hinted(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1905                    Search8hinted(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1906            }
1907    
1908          if (!(inter4v) ||          if (!(inter4v) ||
1909                  (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] +
1910                                                            Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1911  // INTER MODE  // INTER MODE
   
1912                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1913                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1914                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1915    
1916                    pMB->qmvs[0] = pMB->qmvs[1]
1917                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1918    
1919                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1920                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1921    
1922                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1923                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predQMV.x;
1924                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predQMV.y;
1925                    }
1926                    else {
1927                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1928                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1929                    }
1930          } else {          } else {
1931  // INTER4V MODE; all other things are already set in Search8hinted  // INTER4V MODE; all other things are already set in Search8hinted
1932                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1933                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3]
1934                                                    + Data->iMinSAD[4] + IMV16X16 * iQuant;
1935          }          }
1936    
1937  }  }
# Line 1568  Line 1949 
1949          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
1950    
1951          uint32_t x, y;          uint32_t x, y;
1952            uint8_t * qimage;
1953            int32_t temp[5], quant = current->quant;
1954            int32_t iMinSAD[5];
1955            VECTOR currentMV[5], currentQMV[5];
1956            SearchData Data;
1957            Data.iEdgedWidth = pParam->edged_width;
1958            Data.currentMV = currentMV;
1959            Data.currentQMV = currentQMV;
1960            Data.iMinSAD = iMinSAD;
1961            Data.temp = temp;
1962            Data.iFcode = current->fcode;
1963            Data.rounding = pParam->m_rounding_type;
1964    
1965            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
1966                    return; // allocate some mem for qpel interpolated blocks
1967                                      // somehow this is dirty since I think we shouldn't use malloc outside
1968                                      // encoder_create() - so please fix me!
1969    
1970            Data.RefQ = qimage;
1971    
1972          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
1973    
1974          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
1975                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
                         int32_t sad00;  
1976    
1977                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
1978    
1979  //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
1980                          if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;                          if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;
1981    
1982    
1983                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
1984                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
1985                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant; }
1986                            else {
1987                                    if (pMB->dquant != NO_CHANGE) {
1988                                            quant += DQtab[pMB->dquant];
1989                                            if (quant > 31) quant = 31;
1990                                            else if (quant < 1) quant = 1;
1991                                    }
1992                                    pMB->quant = quant;
1993                            }
1994    
1995                          if (pMB->dquant == NO_CHANGE) //no skip otherwise, anyway                          SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
1996                                  sad00 = pMB->sad16                                                          y, current->motion_flags, pMB->quant,
1997                                          = sad16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
1998                                                                  pRef->y + (x + y * pParam->edged_width) * 16,                                                          &Data);
                                                                 pParam->edged_width, 256*4096 );  
                         else sad00 = 256*4096;  
1999    
2000                    }
2001            }
2002            free(qimage);
2003    }
2004    
2005  //initial skip decision  static __inline int
2006    MEanalyzeMB (   const uint8_t * const pRef,
2007                                    const uint8_t * const pCur,
2008                                    const int x,
2009                                    const int y,
2010                                    const MBParam * const pParam,
2011                                    const MACROBLOCK * const pMBs,
2012                                    MACROBLOCK * const pMB,
2013                                    SearchData * const Data)
2014    {
2015    
2016                          if ( (pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)          int i = 255, mask;
2017                                  && ( //(pMB->mode == MODE_NOT_CODED) ||          VECTOR pmv[3];
2018                                          (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant) )) ) {  
2019                                  if (sad00 < pMB->quant * INITIAL_SKIP_THRESH) {          *(Data->iMinSAD) = MV_MAX_ERROR;
2020                                          SkipMacroblockP(pMB, sad00);          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
2021                                          continue; } //skipped          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2022                                    pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
2023    
2024            Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
2025            Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
2026    
2027            CheckCandidate = CheckCandidate16no4vI;
2028    
2029            pmv[1].x = EVEN(pMB->mvs[0].x);
2030            pmv[1].y = EVEN(pMB->mvs[0].y);
2031            pmv[0].x = EVEN(Data->predMV.x);
2032            pmv[0].y = EVEN(Data->predMV.y);
2033            pmv[2].x = pmv[2].y = 0;
2034    
2035            CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, Data);
2036            if (!(mask = make_mask(pmv, 1)))
2037                    CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, Data);
2038            if (!(mask = make_mask(pmv, 2)))
2039                    CheckCandidate16no4vI(0, 0, mask, &i, Data);
2040    
2041            DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
2042    
2043            pMB->mvs[0] = *Data->currentMV;
2044    
2045            return *(Data->iMinSAD);
2046                          }                          }
                         else sad00 = 256*4096;  
2047    
2048                          if (pMB->mode == MODE_NOT_CODED)  #define INTRA_THRESH    1350
2049                                  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);  
2050    
2051                          else  int
2052                                  SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,  MEanalysis(     const IMAGE * const pRef,
2053                                                          y, current->motion_flags, pMB->quant,                          const IMAGE * const pCurrent,
2054                                                          current->fcode, pParam, pMBs,                          MBParam * const pParam,
2055                                                          current->global_flags & XVID_INTER4V, pMB);                          MACROBLOCK * const pMBs,
2056                            const uint32_t iFcode)
2057    {
2058            uint32_t x, y, intra = 0;
2059            int sSAD = 0;
2060    
2061  /* final skip decision, a.k.a. "the vector you found, really that good?" */          VECTOR currentMV;
2062                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)          int32_t iMinSAD;
2063                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)          SearchData Data;
2064                                  SkipMacroblockP(pMB, sad00);          Data.iEdgedWidth = pParam->edged_width;
2065            Data.currentMV = &currentMV;
2066            Data.iMinSAD = &iMinSAD;
2067            Data.iFcode = iFcode;
2068    
2069            if (sadInit) (*sadInit) ();
2070    
2071            for (y = 1; y < pParam->mb_height-1; y++) {
2072                    for (x = 1; x < pParam->mb_width-1; x++) {
2073                            int sad, dev;
2074                            MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2075    
2076                            sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
2077                                                                    pParam, pMBs, pMB, &Data);
2078    
2079                            if (sad > INTRA_THRESH) {
2080                                    dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
2081                                                              pParam->edged_width);
2082                                    if (dev + INTRA_THRESH < sad) intra++;
2083                                    if (intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame
2084                  }                  }
2085                            sSAD += sad;
2086          }          }
2087  }  }
2088            sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2089            if (sSAD > INTER_THRESH ) return 1; //P frame
2090            emms();
2091            return 0; // B frame
2092    
2093    }
2094    
2095    int
2096    FindFcode(      const MBParam * const pParam,
2097                            const FRAMEINFO * const current)
2098    {
2099            uint32_t x, y;
2100            int max = 0, min = 0, i;
2101    
2102            for (y = 0; y < pParam->mb_height; y++) {
2103                    for (x = 0; x < pParam->mb_width; x++) {
2104    
2105                            MACROBLOCK *pMB = &current->mbs[x + y * pParam->mb_width];
2106                            for(i = 0; i < (pMB->mode == MODE_INTER4V ? 4:1); i++) {
2107                                    if (pMB->mvs[i].x > max) max = pMB->mvs[i].x;
2108                                    if (pMB->mvs[i].y > max) max = pMB->mvs[i].y;
2109    
2110                                    if (pMB->mvs[i].x < min) min = pMB->mvs[i].x;
2111                                    if (pMB->mvs[i].y < min) min = pMB->mvs[i].y;
2112                            }
2113                    }
2114            }
2115    
2116            min = -min;
2117            max += 1;
2118            if (min > max) max = min;
2119            if (pParam->m_quarterpel) max *= 2;
2120    
2121            for (i = 1; (max > 32 << (i - 1)); i++);
2122            return i;
2123    }

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

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