[cvs] / xvidcore / src / motion / motion_est.c Repository:
ViewVC logotype

Diff of /xvidcore/src/motion/motion_est.c

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

revision 1.44.2.2, Wed Sep 25 21:27:55 2002 UTC revision 1.44.2.12, 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"
# Line 51  Line 52 
52  #define CHECK_CANDIDATE(X,Y,D) { \  #define CHECK_CANDIDATE(X,Y,D) { \
53  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }
54    
55    #define GET_REFERENCE(X, Y, REF) { \
56            switch ( (((X)&1)<<1) + ((Y)&1) ) \
57            { \
58                    case 0 : REF = (uint8_t *)data->Ref + (X)/2 + ((Y)/2)*(data->iEdgedWidth); break; \
59                    case 1 : REF = (uint8_t *)data->RefV + (X)/2 + (((Y)-1)/2)*(data->iEdgedWidth); break; \
60                    case 2 : REF = (uint8_t *)data->RefH + ((X)-1)/2 + ((Y)/2)*(data->iEdgedWidth); break; \
61                    default : REF = (uint8_t *)data->RefHV + ((X)-1)/2 + (((Y)-1)/2)*(data->iEdgedWidth); break; \
62            } \
63    }
64    
65  #define iDiamondSize 2  #define iDiamondSize 2
66    
67  static __inline int  static __inline int
# Line 84  Line 95 
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;  
98          int t;          int t;
99          const uint8_t * Reference;          const uint8_t * Reference;
100    
# Line 98  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 137  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 148  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)  CheckCandidate16no4vI(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
275  {  {
276          int32_t sad;          int32_t sad;
# Line 155  Line 278 
278          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
279                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
280    
281          sad = lambda_vec16[data->iQuant] *          sad = sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),
                         d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);  
   
         sad += sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),  
282                                          data->iEdgedWidth, 256*4096);                                          data->iEdgedWidth, 256*4096);
283    
284          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
# Line 193  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 216  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 269  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 328  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)) {          if (sad < *(data->iMinSAD)) {
454                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 336  Line 456 
456                  *dir = Direction; }                  *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)) {
480                    *(data->iMinSAD) = sad;
481                    data->currentMV->x = x; data->currentMV->y = y;
482                    *dir = Direction; }
483    }
484    
485    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 */  /* CHECK_CANDIATE FUNCTIONS END */
542    
543  /* MAINSEARCH FUNCTIONS START */  /* MAINSEARCH FUNCTIONS START */
# Line 504  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 517  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 530  Line 754 
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 = 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 = 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 550  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          // some pre-initialized thingies for SearchP
785          int32_t temp[5];          int32_t temp[5];
786          VECTOR currentMV[5];          VECTOR currentMV[5];
787            VECTOR currentQMV[5];
788          int32_t iMinSAD[5];          int32_t iMinSAD[5];
789          SearchData Data;          SearchData Data;
790          Data.iEdgedWidth = pParam->edged_width;          Data.iEdgedWidth = pParam->edged_width;
791          Data.currentMV = currentMV;          Data.currentMV = currentMV;
792            Data.currentQMV = currentQMV;
793          Data.iMinSAD = iMinSAD;          Data.iMinSAD = iMinSAD;
794          Data.temp = temp;          Data.temp = temp;
795          Data.iFcode = current->fcode;          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 576  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                                                  &Data, 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 613  Line 859 
859                                                    pParam->edged_width);                                                    pParam->edged_width);
860    
861                                  if (deviation < (pMB->sad16 - InterBias)) {                                  if (deviation < (pMB->sad16 - InterBias)) {
862                                          if (++iIntra >= iLimit) return 1;                                          if (++iIntra >= iLimit) { free(qimage); return 1; }
863                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
864                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
865                                                          pMB->mvs[3] = zeroMV;                                                          pMB->mvs[3] = zeroMV;
866                                            pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] =
867                                                            pMB->qmvs[3] = zeroMV;
868                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
869                                                  pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
870                                  }                                  }
871                          }                          }
872                  }                  }
873          }          }
874            free(qimage);
875          return 0;          return 0;
876  }  }
877    
# Line 684  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,
# Line 702  Line 952 
952    
953          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()
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, Data->iFcode);                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
956    
957          Data->predMV = pmv[0];          Data->predMV = pmv[0];
958    
959          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
960          Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;          Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;
961          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
962          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
963          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
964            Data->RefQ = pRefQ;
965    
966          Data->iQuant = iQuant;          Data->lambda16 = lambda_vec16[iQuant];
967            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);
# Line 719  Line 972 
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); }
974    
975          for(i = 0;  i < 5; i++) Data->iMinSAD[i] = 256*4096;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
   
         if (inter4v) CheckCandidate = CheckCandidate16;  
         else CheckCandidate = CheckCandidate16no4v;  
976    
977          (*CheckCandidate)(Data->predMV.x, Data->predMV.y, 0, &iDirection, Data);          for(i = 0;  i < 5; i++)
978                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
979    
980          for(i = 0;  i < 5; i++) Data->currentMV[i].x = Data->currentMV[i].y = 0;          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    
         i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);  
985          Data->iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;          Data->iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;
986          Data->iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;          Data->iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;
987          Data->iMinSAD[2] = pMB->sad8[1];          Data->iMinSAD[2] = pMB->sad8[1];
988          Data->iMinSAD[3] = pMB->sad8[2];          Data->iMinSAD[3] = pMB->sad8[2];
989          Data->iMinSAD[4] = pMB->sad8[3];          Data->iMinSAD[4] = pMB->sad8[3];
990    
         if (pMB->dquant != NO_CHANGE) inter4v = 0;  
   
991          if ((x == 0) && (y == 0)) threshA = 512;          if ((x == 0) && (y == 0)) threshA = 512;
992          else {          else {
993                  threshA = Data->temp[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;
1003                    else CheckCandidate = CheckCandidate16no4v;
1004    
1005  /* main loop. checking all predictions */  /* main loop. checking all predictions */
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 (Data->iMinSAD[0] <= threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1011          }          }
1012    
# Line 779  Line 1035 
1035                          if (!(MVequal(startMV, backupMV))) {                          if (!(MVequal(startMV, backupMV))) {
1036                                  bSAD = Data->iMinSAD[0]; Data->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 < Data->iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1041                                          Data->currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
# Line 792  Line 1048 
1048                          if (!(MVequal(startMV, backupMV))) {                          if (!(MVequal(startMV, backupMV))) {
1049                                  bSAD = Data->iMinSAD[0]; Data->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 < Data->iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1054                                          Data->currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
# Line 803  Line 1059 
1059    
1060          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);          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((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1068    
1069                    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                    QuarterpelRefine(Data);
1074            }
1075    
1076          if (inter4v) {          if (inter4v) {
1077                  SearchData Data8;                  SearchData Data8;
1078                  Data8.iFcode = Data->iFcode;                  Data8.iFcode = Data->iFcode;
1079                  Data8.iQuant = Data->iQuant;                  Data8.lambda8 = Data->lambda8;
1080                  Data8.iEdgedWidth = Data->iEdgedWidth;                  Data8.iEdgedWidth = Data->iEdgedWidth;
1081                    Data8.RefQ = Data->RefQ;
1082                  Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);                  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);                  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);                  Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
# Line 822  Line 1093 
1093                  pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1094                          = pMB->mvs[2] = pMB->mvs[3] = Data->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] =  Data->iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1101    
1102                    if(pParam->m_quarterpel) {
1103                            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;                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1108                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;                  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 = Data->iMinSAD[1] + Data->iMinSAD[2] +                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1114                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1115          }          }
   
1116  }  }
1117    
1118  static void  static void
# Line 846  Line 1125 
1125                  const int block,                  const int block,
1126                  SearchData * const Data)                  SearchData * const Data)
1127  {  {
         Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);  
1128          Data->iMinSAD = OldData->iMinSAD + 1 + block;          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1129          Data->currentMV = OldData->currentMV + 1 + block;          Data->currentMV = OldData->currentMV + 1 + block;
1130            Data->currentQMV = OldData->currentQMV + 1 + block;
1131    
1132          if (block != 0)          if(pParam->m_quarterpel) {
1133                  *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *                  Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1134                    if (block != 0) *(Data->iMinSAD) += Data->lambda8 *
1135                                                                            d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1136                                                                                                    Data->currentQMV->y - Data->predQMV.y,
1137                                                                                                    Data->iFcode);
1138                    CheckCandidate = CheckCandidate8Q;
1139            } else {
1140                    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,                                                                  d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1143                                                                                          Data->currentMV->y - Data->predMV.y,                                                                                          Data->currentMV->y - Data->predMV.y,
1144                                                                                          Data->iFcode);                                                                                          Data->iFcode);
1145                    CheckCandidate = CheckCandidate8;
1146            }
1147    
1148          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
1149    
# Line 866  Line 1155 
1155                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
1156    
1157                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1158                                  pParam->width, pParam->height, OldData->iFcode);                                  pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
   
                 CheckCandidate = CheckCandidate8;  
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 (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(Data);                          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(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;          pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1204          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1205            }
1206    
1207          pMB->mvs[block] = *(Data->currentMV);          pMB->mvs[block] = *(Data->currentMV);
1208          pMB->sad8[block] =  4 * (*Data->iMinSAD);          pMB->qmvs[block] = *(Data->currentQMV);
1209    
1210            pMB->sad8[block] =  4 * (*Data->iMinSAD);
1211  }  }
1212    
1213  /* B-frames code starts here */  /* B-frames code starts here */
# Line 947  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 1008  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 (*Data->iMinSAD < *best_sad) {
1327          if (iMinSAD < *best_sad) {                  *best_sad = *Data->iMinSAD;
                 *best_sad = 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  }  }
# Line 1041  Line 1346 
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 = 266*4096, 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->y + (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->y + (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;
1384    
1385                  if (( pMB->mvs[k].x > Data.max_dx ) || ( pMB->mvs[k].x < Data.min_dx )                  if ( ( pMB->b_mvs[k].x > Data->max_dx ) || ( pMB->b_mvs[k].x < Data->min_dx )
1386                          || ( pMB->mvs[k].y > Data.max_dy ) || ( pMB->mvs[k].y < Data.min_dy )                          || ( pMB->b_mvs[k].y > Data->max_dy ) || ( pMB->b_mvs[k].y < Data->min_dy )) {
                         || ( pMB->b_mvs[k].x > Data.max_dx ) || ( pMB->b_mvs[k].x < Data.min_dx )  
                         || ( pMB->b_mvs[k].y > Data.max_dy ) || ( pMB->b_mvs[k].y < Data.min_dy )) {  
1387    
1388                          *best_sad = 256*4096; // in that case, we won't use direct mode                          *best_sad = 256*4096; // in that case, we won't use direct mode
1389                          pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"                          pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
# Line 1100  Line 1393 
1393                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1394                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1395                          pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];                          pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];
1396                          Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1397                          Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1398                          break;                          break;
1399                  }                  }
1400          }          }
# Line 1110  Line 1403 
1403                  CheckCandidate = CheckCandidateDirect;                  CheckCandidate = CheckCandidateDirect;
1404          else CheckCandidate = CheckCandidateDirectno4v;          else CheckCandidate = CheckCandidateDirectno4v;
1405    
1406          (*CheckCandidate)(0, 0, 255, &k, &Data);          (*CheckCandidate)(0, 0, 255, &k, Data);
1407    
1408  // skip decision  // skip decision
1409          if (iMinSAD - 2 * lambda_vec16[iQuant] < (int32_t)iQuant * SKIP_THRESH_B) {          if (*Data->iMinSAD - 2 * Data->lambda16 < (uint32_t)pMB->quant * SKIP_THRESH_B) {
1410                  //checking chroma. everything copied from MC                  //possible skip - checking chroma. everything copied from MC
1411                  //this is not full chroma compensation, only it's fullpel approximation. should work though                  //this is not full chroma compensation, only it's fullpel approximation. should work though
1412                  int sum, dx, dy, b_dx, b_dy;                  int sum, dx, dy, b_dx, b_dy;
1413    
# Line 1130  Line 1423 
1423                  sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;                  sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;
1424                  b_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));                  b_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1425    
1426                  sum = sad8bi(pCur->u + 8*x + 8*y*(iEdgedWidth/2),                  sum = sad8bi(pCur->u + 8*x + 8*y*(Data->iEdgedWidth/2),
1427                                          f_Ref->u + (y*8 + dy/2) * (iEdgedWidth/2) + x*8 + dx/2,                                          f_Ref->u + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1428                                          b_Ref->u + (y*8 + b_dy/2) * (iEdgedWidth/2) + x*8 + b_dx/2,                                          b_Ref->u + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1429                                          iEdgedWidth/2);                                          Data->iEdgedWidth/2);
1430                  sum += sad8bi(pCur->v + 8*x + 8*y*(iEdgedWidth/2),                  sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1431                                          f_Ref->v + (y*8 + dy/2) * (iEdgedWidth/2) + x*8 + dx/2,                                          f_Ref->v + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1432                                          b_Ref->v + (y*8 + b_dy/2) * (iEdgedWidth/2) + x*8 + b_dx/2,                                          b_Ref->v + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1433                                          iEdgedWidth/2);                                          Data->iEdgedWidth/2);
1434    
1435                  if ((uint32_t) sum < MAX_CHROMA_SAD_FOR_SKIP * Data.iQuant) {                  if (sum < MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) {
1436                          pMB->mode = MODE_DIRECT_NONE_MV;                          pMB->mode = MODE_DIRECT_NONE_MV;
1437                          return iMinSAD;                          return *Data->iMinSAD;
1438                  }                  }
1439          }          }
1440    
1441          skip_sad = iMinSAD;          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
# Line 1154  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 1199  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;  
1509    
1510          fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          *(bData.iMinSAD = fData->iMinSAD) = 4096*256;
1511          fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;          bData.Cur = fData->Cur;
1512          fData.currentMV = currentMV; bData.currentMV = currentMV + 1;          fData->iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;
1513          fData.iQuant = bData.iQuant = iQuant;          bData.currentMV = fData->currentMV + 1;
1514          fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;          bData.lambda16 = fData->lambda16;
1515            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1516          bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  
1517          bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;          bData.bRef = fData->Ref = f_Ref + (x + y * iEdgedWidth) * 16;
1518          bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;          bData.bRefH = fData->RefH = f_RefH + (x + y * iEdgedWidth) * 16;
1519          bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;          bData.bRefV = fData->RefV = f_RefV + (x + y * iEdgedWidth) * 16;
1520          bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;          bData.bRefHV = fData->RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;
1521          bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;          bData.Ref = fData->bRef = b_Ref + (x + y * iEdgedWidth) * 16;
1522          bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;          bData.RefH = fData->bRefH = b_RefH + (x + y * iEdgedWidth) * 16;
1523          bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;          bData.RefV = fData->bRefV = b_RefV + (x + y * iEdgedWidth) * 16;
1524            bData.RefHV = fData->bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;
1525          bData.bpredMV = fData.predMV = *f_predMV;  
1526          fData.bpredMV = bData.predMV = *b_predMV;          bData.bpredMV = fData->predMV = *f_predMV;
1527            fData->bpredMV = bData.predMV = *b_predMV;
1528          currentMV[0] = pMB->mvs[0];  
1529          currentMV[1] = pMB->b_mvs[0];          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);          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);          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 (currentMV[0].x > fData.max_dx) currentMV[0].x = fData.max_dx;          if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1534          if (currentMV[0].x < fData.min_dx) currentMV[0].x = fData.min_dy;          if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dy;
1535          if (currentMV[0].y > fData.max_dy) currentMV[0].y = fData.max_dx;          if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dx;
1536          if (currentMV[0].y > fData.min_dy) currentMV[0].y = fData.min_dy;          if (fData->currentMV[0].y > fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1537    
1538          if (currentMV[1].x > bData.max_dx) currentMV[1].x = bData.max_dx;          if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1539          if (currentMV[1].x < bData.min_dx) currentMV[1].x = bData.min_dy;          if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dy;
1540          if (currentMV[1].y > bData.max_dy) currentMV[1].y = bData.max_dx;          if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dx;
1541          if (currentMV[1].y > bData.min_dy) currentMV[1].y = bData.min_dy;          if (fData->currentMV[1].y > bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1542    
1543          CheckCandidateInt(currentMV[0].x, currentMV[0].y, 255, &iDirection, &fData);          CheckCandidateInt(fData->currentMV[0].x, fData->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 + 1, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1553                  CheckCandidateInt(i, j + 1, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1554                  CheckCandidateInt(i - 1, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1555                  CheckCandidateInt(i, j - 1, 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 + 1, j, 0, &iDirection, &bData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1562                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
# Line 1280  Line 1566 
1566          } while (!(iDirection));          } while (!(iDirection));
1567    
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 1294  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 1322  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 1338  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    
# Line 1346  Line 1646 
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    
1655                          if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                          if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1656    
# Line 1361  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 1381  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 1416  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->currentMV = OldData->currentMV + 1 + block;
1734            Data->currentQMV = OldData->currentQMV + 1 + block;
1735            Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1736    
1737          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          if(pParam->m_quarterpel) {
1738          Data.iMinSAD = OldData->iMinSAD + 1 + block;                  Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1739          Data.currentMV = OldData->currentMV+1+block;                  if (block != 0) *(Data->iMinSAD) += Data->lambda8 *
1740          Data.iFcode = OldData->iFcode;                                                                          d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1741          Data.iQuant = OldData->iQuant;                                                                                                  Data->currentQMV->y - Data->predQMV.y,
1742                                                                                                    Data->iFcode);
1743          Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));                  CheckCandidate = CheckCandidate8Q;
1744          Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));          } else {
1745          Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  if (block != 0) *(Data->iMinSAD) += Data->lambda8 *
1746          Data.RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));                                                                          d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1747          Data.iEdgedWidth = pParam->edged_width;                                                                                                  Data->currentMV->y - Data->predMV.y,
1748          Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                                                                                                  Data->iFcode);
   
1749          CheckCandidate = CheckCandidate8;          CheckCandidate = CheckCandidate8;
1750            }
1751    
1752          if (block != 0)          Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));
1753                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *          Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));
1754                                                                  d_mv_bits(      Data.currentMV->x - Data.predMV.x,          Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1755                                                                                          Data.currentMV->y - Data.predMV.y,          Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));
                                                                                         Data.iFcode);  
1756    
1757            Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
1758    
1759          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1760                                  pParam->width, pParam->height, OldData->iFcode);                                  pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1761    
1762          if (pMB->mode == MODE_INTER4V) {          temp_sad = *(Data->iMinSAD); // store current MinSAD
                 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(*(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          if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                  HalfpelRefine(Data); // perform halfpel refine of current best vector
1779    
1780          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;                  if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1781          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;                          Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1782          pMB->mvs[block] = *(Data.currentMV);                          Data->currentQMV->y = 2 * Data->currentMV->y;
1783          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                  }
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 1482  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 1553  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->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 1595  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    
# Line 1606  Line 1979 
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                          SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
1996                                                          y, current->motion_flags, pMB->quant,                                                          y, current->motion_flags, pMB->quant,
1997                                                          current->fcode, pParam, pMBs,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
1998                                                          current->global_flags & XVID_INTER4V, pMB);                                                          &Data);
1999    
2000                  }                  }
2001          }          }
2002            free(qimage);
2003  }  }
2004    
2005  static __inline int  static __inline int
# Line 1624  Line 2007 
2007                                  const uint8_t * const pCur,                                  const uint8_t * const pCur,
2008                                  const int x,                                  const int x,
2009                                  const int y,                                  const int y,
                                 const uint32_t iFcode,  
2010                                  const MBParam * const pParam,                                  const MBParam * const pParam,
2011                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
2012                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
2013                                    SearchData * const Data)
2014  {  {
2015    
2016          const int32_t iEdgedWidth = pParam->edged_width;          int i = 255, mask;
2017          int i, mask;          VECTOR pmv[3];
         VECTOR currentMV, pmv[3];  
         int32_t iMinSAD = MV_MAX_ERROR;  
         SearchData Data;  
2018    
2019          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          *(Data->iMinSAD) = MV_MAX_ERROR;
2020          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
2021                                  pParam->width, pParam->height, iFcode);          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 * iEdgedWidth) * 16;          Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
2025          Data.iEdgedWidth = iEdgedWidth;          Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
         Data.currentMV = &currentMV;  
         Data.iMinSAD = &iMinSAD;  
         Data.Ref = pRef + (x + iEdgedWidth*y)*16;  
         Data.iQuant = 2;  
         Data.iFcode = iFcode;  
2026    
2027          CheckCandidate = CheckCandidate16no4vI;          CheckCandidate = CheckCandidate16no4vI;
2028    
2029          pmv[1].x = EVEN(pMB->mvs[0].x);          pmv[1].x = EVEN(pMB->mvs[0].x);
2030          pmv[1].y = EVEN(pMB->mvs[0].y);          pmv[1].y = EVEN(pMB->mvs[0].y);
2031          pmv[0].x = EVEN(Data.predMV.x);          pmv[0].x = EVEN(Data->predMV.x);
2032          pmv[0].y = EVEN(Data.predMV.y);          pmv[0].y = EVEN(Data->predMV.y);
2033          pmv[2].x = pmv[2].y = 0;          pmv[2].x = pmv[2].y = 0;
2034    
2035          CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, &Data);          CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, Data);
2036          if (!(mask = make_mask(pmv, 1)))          if (!(mask = make_mask(pmv, 1)))
2037                  CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, &Data);                  CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, Data);
2038          if (!(mask = make_mask(pmv, 2)))          if (!(mask = make_mask(pmv, 2)))
2039                  CheckCandidate16no4vI(0, 0, mask, &i, &Data);                  CheckCandidate16no4vI(0, 0, mask, &i, Data);
2040    
2041          DiamondSearch(currentMV.x, currentMV.y, &Data, i);          DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
2042    
2043          pMB->mvs[0] = pMB->mvs[1]          pMB->mvs[0] = *Data->currentMV;
                         = pMB->mvs[2] = pMB->mvs[3] = currentMV; // all, for future get_pmv()  
2044    
2045          return iMinSAD;          return *(Data->iMinSAD);
2046  }  }
2047    
2048  #define INTRA_THRESH    1350  #define INTRA_THRESH    1350
# Line 1683  Line 2058 
2058          uint32_t x, y, intra = 0;          uint32_t x, y, intra = 0;
2059          int sSAD = 0;          int sSAD = 0;
2060    
2061            VECTOR currentMV;
2062            int32_t iMinSAD;
2063            SearchData Data;
2064            Data.iEdgedWidth = pParam->edged_width;
2065            Data.currentMV = &currentMV;
2066            Data.iMinSAD = &iMinSAD;
2067            Data.iFcode = iFcode;
2068    
2069          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
2070    
2071          for (y = 0; y < pParam->mb_height-1; y++) {          for (y = 1; y < pParam->mb_height-1; y++) {
2072                  for (x = 0; x < pParam->mb_width; x++) {                  for (x = 1; x < pParam->mb_width-1; x++) {
2073                          int sad, dev;                          int sad, dev;
   
2074                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2075    
2076                          sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,                          sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
2077                                                                  iFcode, pParam, pMBs, pMB);                                                                  pParam, pMBs, pMB, &Data);
2078    
                         if ( x != 0 && y != 0 && x != pParam->mb_width-1 ) { //no edge macroblocks, they just don't work  
2079                                  if (sad > INTRA_THRESH) {                                  if (sad > INTRA_THRESH) {
2080                                          dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                          dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
2081                                                                    pParam->edged_width);                                                                    pParam->edged_width);
# Line 1703  Line 2084 
2084                                  }                                  }
2085                                  sSAD += sad;                                  sSAD += sad;
2086                          }                          }
   
                 }  
2087          }          }
2088          sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);          sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2089          if (sSAD > INTER_THRESH ) return 1; //P frame          if (sSAD > INTER_THRESH ) return 1; //P frame
# Line 1712  Line 2091 
2091          return 0; // B frame          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.1.44.2.2  
changed lines
  Added in v.1.44.2.12

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