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

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

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

revision 539, Wed Sep 25 21:28:48 2002 UTC revision 619, Sat Nov 2 15:52:31 2002 UTC
# Line 37  Line 37 
37  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
38  #include "../global.h"  #include "../global.h"
39  #include "../utils/timer.h"  #include "../utils/timer.h"
40    #include "../image/interpolate8x8.h"
41  #include "motion_est.h"  #include "motion_est.h"
42  #include "motion.h"  #include "motion.h"
43  #include "sad.h"  #include "sad.h"
# 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)) {
454                    *(data->iMinSAD) = sad;
455                    data->currentMV->x = x; data->currentMV->y = y;
456                    *dir = Direction; }
457    }
458    
459    static void
460    CheckCandidate8Q(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
461    {
462            int32_t sad;
463            const uint8_t * Reference;
464    
465            if (( x > data->max_dx) || ( x < data->min_dx)
466                    || ( y > data->max_dy) || (y < data->min_dy)) return;
467    
468            switch ( ((x&1)<<1) + (y&1) )
469            {
470                    case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;
471                    case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;
472                    case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;
473                    default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;
474            }
475    
476            sad = sad8(data->Cur, Reference, data->iEdgedWidth);
477            sad += data->lambda8 * d_mv_bits(2 * x - data->predQMV.x, 2 * y - data->predQMV.y, data->iFcode);
478    
479          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
480                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 336  Line 482 
482                  *dir = Direction; }                  *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            pMB->qmvs[0].x = pMB->qmvs[1].x = pMB->qmvs[2].x = pMB->qmvs[3].x = 0;
758            pMB->qmvs[0].y = pMB->qmvs[1].y = pMB->qmvs[2].y = pMB->qmvs[3].y = 0;
759    
760          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = sad;          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = sad;
761  }  }
762    
# Line 550  Line 777 
777    
778          uint32_t x, y;          uint32_t x, y;
779          uint32_t iIntra = 0;          uint32_t iIntra = 0;
780          int32_t InterBias;          int32_t InterBias, quant = current->quant;
781            uint8_t *qimage;
782    
783          // some pre-initialized thingies for SearchP          // some pre-initialized thingies for SearchP
784          int32_t temp[5];          int32_t temp[5];
785          VECTOR currentMV[5];          VECTOR currentMV[5];
786            VECTOR currentQMV[5];
787          int32_t iMinSAD[5];          int32_t iMinSAD[5];
788          SearchData Data;          SearchData Data;
789          Data.iEdgedWidth = pParam->edged_width;          Data.iEdgedWidth = pParam->edged_width;
790          Data.currentMV = currentMV;          Data.currentMV = currentMV;
791            Data.currentQMV = currentQMV;
792          Data.iMinSAD = iMinSAD;          Data.iMinSAD = iMinSAD;
793          Data.temp = temp;          Data.temp = temp;
794          Data.iFcode = current->fcode;          Data.iFcode = current->fcode;
795            Data.rounding = pParam->m_rounding_type;
796    
797            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
798                    return 1; // allocate some mem for qpel interpolated blocks
799                                      // somehow this is dirty since I think we shouldn't use malloc outside
800                                      // encoder_create() - so please fix me!
801    
802          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
803    
# Line 576  Line 812 
812    
813                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
814                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
815                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant;
816                            } else {
817                                    if (pMB->dquant != NO_CHANGE) {
818                                            quant += DQtab[pMB->dquant];
819                                            if (quant > 31) quant = 31;
820                                            else if (quant < 1) quant = 1;
821                                    }
822                                    pMB->quant = quant;
823                            }
824    
825  //initial skip decision  /* initial skip decision */
826    /* no early skip for GMC (global vector = skip vector is unknown!)  */
827    
828                          if ((pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)                          if (current->coding_type == P_VOP)      { /* no fast SKIP for S(GMC)-VOPs */
829                                  && (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) ) {                                  if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * INITIAL_SKIP_THRESH)
830                                  if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {                                          if (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
831                                                  SkipMacroblockP(pMB, sad00);                                                  SkipMacroblockP(pMB, sad00);
832                                                  continue;                                                  continue;
833                                  }                                  }
834                          } else sad00 = 256*4096; // skip not allowed - for final skip decision                          }
835    
836                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, qimage, pCurrent, x,
837                                                  y, current->motion_flags, pMB->quant,                                                  y, current->motion_flags, pMB->quant,
838                                                  &Data, pParam, pMBs, reference->mbs,                                                  &Data, pParam, pMBs, reference->mbs,
839                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
840    
841  /* final skip decision, a.k.a. "the vector you found, really that good?" */  /* final skip decision, a.k.a. "the vector you found, really that good?" */
842                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)                          if (current->coding_type == P_VOP)      {
843                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)                                  if ( (pMB->dquant == NO_CHANGE) && (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)
844                                  { SkipMacroblockP(pMB, sad00); continue; }                                  && ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH) )
845                                            if (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
846                                                    SkipMacroblockP(pMB, sad00);
847                                                    continue;
848                                            }
849                            }
850    
851  /* finally, intra decision */  /* finally, intra decision */
852    
# Line 613  Line 863 
863                                                    pParam->edged_width);                                                    pParam->edged_width);
864    
865                                  if (deviation < (pMB->sad16 - InterBias)) {                                  if (deviation < (pMB->sad16 - InterBias)) {
866                                          if (++iIntra >= iLimit) return 1;                                          if (++iIntra >= iLimit) { free(qimage); return 1; }
867                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
868                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
869                                                          pMB->mvs[3] = zeroMV;                                                          pMB->mvs[3] = zeroMV;
870                                            pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] =
871                                                            pMB->qmvs[3] = zeroMV;
872                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
873                                                  pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
874                                  }                                  }
875                          }                          }
876                  }                  }
877          }          }
878            free(qimage);
879    
880            if (current->coding_type == S_VOP)      /* first GMC step only for S(GMC)-VOPs */
881                    current->GMC_MV = GlobalMotionEst( pMBs, pParam, current->fcode );
882            else
883                    current->GMC_MV = zeroMV;
884    
885          return 0;          return 0;
886  }  }
887    
# Line 684  Line 943 
943                  const uint8_t * const pRefH,                  const uint8_t * const pRefH,
944                  const uint8_t * const pRefV,                  const uint8_t * const pRefV,
945                  const uint8_t * const pRefHV,                  const uint8_t * const pRefHV,
946                    const uint8_t * const pRefQ,
947                  const IMAGE * const pCur,                  const IMAGE * const pCur,
948                  const int x,                  const int x,
949                  const int y,                  const int y,
# Line 702  Line 962 
962    
963          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)()
964          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
965                                  pParam->width, pParam->height, Data->iFcode);                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
966    
967          Data->predMV = pmv[0];          Data->predMV = pmv[0];
968    
969          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
970          Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;          Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;
971          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
972          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
973          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
974            Data->RefQ = pRefQ;
975    
976          Data->iQuant = iQuant;          Data->lambda16 = lambda_vec16[iQuant];
977            Data->lambda8 = lambda_vec8[iQuant];
978    
979          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
980                  Data->min_dx = EVEN(Data->min_dx);                  Data->min_dx = EVEN(Data->min_dx);
# Line 719  Line 982 
982                  Data->min_dy = EVEN(Data->min_dy);                  Data->min_dy = EVEN(Data->min_dy);
983                  Data->max_dy = EVEN(Data->max_dy); }                  Data->max_dy = EVEN(Data->max_dy); }
984    
985          for(i = 0;  i < 5; i++) Data->iMinSAD[i] = 256*4096;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
   
         if (inter4v) CheckCandidate = CheckCandidate16;  
         else CheckCandidate = CheckCandidate16no4v;  
986    
987          (*CheckCandidate)(Data->predMV.x, Data->predMV.y, 0, &iDirection, Data);          for(i = 0;  i < 5; i++)
988                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
989    
990          for(i = 0;  i < 5; i++) Data->currentMV[i].x = Data->currentMV[i].y = 0;          if (pParam->m_quarterpel) {
991                    Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
992                    i = d_mv_bits(Data->predQMV.x, Data->predQMV.y, Data->iFcode);
993            } else i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);
994    
         i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);  
995          Data->iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;          Data->iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;
996          Data->iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;          Data->iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;
997          Data->iMinSAD[2] = pMB->sad8[1];          Data->iMinSAD[2] = pMB->sad8[1];
998          Data->iMinSAD[3] = pMB->sad8[2];          Data->iMinSAD[3] = pMB->sad8[2];
999          Data->iMinSAD[4] = pMB->sad8[3];          Data->iMinSAD[4] = pMB->sad8[3];
1000    
         if (pMB->dquant != NO_CHANGE) inter4v = 0;  
   
1001          if ((x == 0) && (y == 0)) threshA = 512;          if ((x == 0) && (y == 0)) threshA = 512;
1002          else {          else {
1003                  threshA = Data->temp[0] + 20;                  threshA = Data->temp[0]; // that's when we keep this SAD atm
1004                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
1005                  if (threshA > 1024) threshA = 1024; }                  if (threshA > 1024) threshA = 1024; }
1006    
1007          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,
1008                                          prevMBs + x + y * pParam->mb_width);                                          prevMBs + x + y * pParam->mb_width);
1009    
1010            if (pParam->m_quarterpel) CheckCandidate = CheckCandidate16Q;
1011            else
1012                    if (inter4v) CheckCandidate = CheckCandidate16;
1013                    else CheckCandidate = CheckCandidate16no4v;
1014    
1015  /* main loop. checking all predictions */  /* main loop. checking all predictions */
1016    
1017          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
1018                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1019                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, Data);                  (*CheckCandidate)(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1020                  if (Data->iMinSAD[0] <= threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1021          }          }
1022    
# Line 779  Line 1045 
1045                          if (!(MVequal(startMV, backupMV))) {                          if (!(MVequal(startMV, backupMV))) {
1046                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1047    
1048                                  CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1049                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1050                                  if (bSAD < Data->iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1051                                          Data->currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
# Line 792  Line 1058 
1058                          if (!(MVequal(startMV, backupMV))) {                          if (!(MVequal(startMV, backupMV))) {
1059                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1060    
1061                                  CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1062                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1063                                  if (bSAD < Data->iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1064                                          Data->currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
# Line 803  Line 1069 
1069    
1070          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1071    
1072            for(i = 0; i < 5; i++) {
1073                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1074                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1075            }
1076    
1077            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1078    
1079                    CheckCandidate = CheckCandidate16_qpel;
1080                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1081                                    pParam->width, pParam->height, Data->iFcode, 0);
1082    
1083                    QuarterpelRefine(Data);
1084            }
1085    
1086          if (inter4v) {          if (inter4v) {
1087                  SearchData Data8;                  SearchData Data8;
1088                  Data8.iFcode = Data->iFcode;                  Data8.iFcode = Data->iFcode;
1089                  Data8.iQuant = Data->iQuant;                  Data8.lambda8 = Data->lambda8;
1090                  Data8.iEdgedWidth = Data->iEdgedWidth;                  Data8.iEdgedWidth = Data->iEdgedWidth;
1091                    Data8.RefQ = Data->RefQ;
1092                  Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);                  Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1093                  Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);                  Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1094                  Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);                  Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
# Line 822  Line 1103 
1103                  pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1104                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1105    
1106                    pMB->qmvs[0] = pMB->qmvs[1]
1107                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1108    
1109                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1110                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1111    
1112                    if(pParam->m_quarterpel) {
1113                            pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predQMV.x;
1114                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predQMV.y;
1115                    }
1116                    else {
1117                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1118                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1119                    }
1120          } else {          } else {
1121  // INTER4V MODE; all other things are already set in Search8  // INTER4V MODE; all other things are already set in Search8
1122                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1123                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1124                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1125          }          }
   
1126  }  }
1127    
1128  static void  static void
# Line 846  Line 1135 
1135                  const int block,                  const int block,
1136                  SearchData * const Data)                  SearchData * const Data)
1137  {  {
         Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);  
1138          Data->iMinSAD = OldData->iMinSAD + 1 + block;          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1139          Data->currentMV = OldData->currentMV + 1 + block;          Data->currentMV = OldData->currentMV + 1 + block;
1140            Data->currentQMV = OldData->currentQMV + 1 + block;
1141    
1142          if (block != 0)          if(pParam->m_quarterpel) {
1143                  *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *                  Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1144                    if (block != 0) *(Data->iMinSAD) += Data->lambda8 *
1145                                                                            d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1146                                                                                                    Data->currentQMV->y - Data->predQMV.y,
1147                                                                                                    Data->iFcode);
1148                    CheckCandidate = CheckCandidate8Q;
1149            } else {
1150                    Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1151                    if (block != 0) *(Data->iMinSAD) += Data->lambda8 *
1152                                                                  d_mv_bits(      Data->currentMV->x - Data->predMV.x,                                                                  d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1153                                                                                          Data->currentMV->y - Data->predMV.y,                                                                                          Data->currentMV->y - Data->predMV.y,
1154                                                                                          Data->iFcode);                                                                                          Data->iFcode);
1155                    CheckCandidate = CheckCandidate8;
1156            }
1157    
1158          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
1159    
# Line 866  Line 1165 
1165                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
1166    
1167                  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,
1168                                  pParam->width, pParam->height, OldData->iFcode);                                  pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
   
                 CheckCandidate = CheckCandidate8;  
1169    
1170                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & PMV_EXTSEARCH8) {
1171                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1172    
1173                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1174                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1175                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1176                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1177    
1178                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);    }                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1179    
1180                            if(*(Data->iMinSAD) < temp_sad) {
1181                                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1182                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1183                            }
1184                    }
1185    
1186                    if (MotionFlags & PMV_HALFPELREFINE8) {
1187                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1188    
1189                            HalfpelRefine(Data); // perform halfpel refine of current best vector
1190    
1191                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(Data);                          if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1192                                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1193                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1194                            }
1195          }          }
1196    
1197                    if(pParam->m_quarterpel) {
1198                            if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1199                                    (MotionFlags & PMV_QUARTERPELREFINE8)) {
1200                            CheckCandidate = CheckCandidate8_qpel;
1201                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1202                                    pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1203                            QuarterpelRefine(Data);
1204                            }
1205                    }
1206            }
1207    
1208            if(pParam->m_quarterpel) {
1209                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predQMV.x;
1210                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predQMV.y;
1211            }
1212            else {
1213          pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;          pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1214          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1215            }
1216    
1217          pMB->mvs[block] = *(Data->currentMV);          pMB->mvs[block] = *(Data->currentMV);
1218          pMB->sad8[block] =  4 * (*Data->iMinSAD);          pMB->qmvs[block] = *(Data->currentQMV);
1219    
1220            pMB->sad8[block] =  4 * (*Data->iMinSAD);
1221  }  }
1222    
1223  /* B-frames code starts here */  /* B-frames code starts here */
# Line 947  Line 1278 
1278                          const IMAGE * const pCur,                          const IMAGE * const pCur,
1279                          const int x, const int y,                          const int x, const int y,
1280                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
1281                          const uint32_t iFcode,                          const uint32_t iFcode,
1282                          const MBParam * const pParam,                          const MBParam * const pParam,
1283                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
1284                          const VECTOR * const predMV,                          const VECTOR * const predMV,
1285                          int32_t * const best_sad,                          int32_t * const best_sad,
1286                          const int32_t mode_current)                          const int32_t mode_current,
1287                            SearchData * const Data)
1288  {  {
1289    
1290          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1291    
1292          int i, iDirection, mask;          int i, iDirection, mask;
1293          VECTOR currentMV, pmv[7];          VECTOR pmv[7];
1294          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1295          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
1296          SearchData Data;          Data->iFcode = iFcode;
   
         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;  
1297    
1298          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,          Data->Ref = pRef + (x + y * iEdgedWidth) * 16;
1299                                  pParam->width, pParam->height, iFcode);          Data->RefH = pRefH + (x + y * iEdgedWidth) * 16;
1300            Data->RefV = pRefV + (x + y * iEdgedWidth) * 16;
1301            Data->RefHV = pRefHV + (x + y * iEdgedWidth) * 16;
1302    
1303          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?  
1304    
1305            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1306                                    pParam->width, pParam->height, iFcode, pParam->m_quarterpel);
1307    
1308          pmv[0] = Data.predMV;          pmv[0] = Data->predMV;
1309          PreparePredictionsBF(pmv, x, y, pParam->mb_width,          PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
                                         pMB, mode_current);  
1310    
1311          currentMV.x = currentMV.y = 0;          Data->currentMV->x = Data->currentMV->y = 0;
1312    
1313          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1314    
1315  // main loop. checking all predictions  // main loop. checking all predictions
1316          for (i = 0; i < 8; i++) {          for (i = 0; i < 8; i++) {
1317                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1318                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1319          }          }
1320    
1321          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1008  Line 1324 
1324                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1325                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1326    
1327          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1328    
1329          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          HalfpelRefine(Data);
1330    
1331  // three bits are needed to code backward mode. four for forward  // three bits are needed to code backward mode. four for forward
1332  // we treat the bits just like they were vector's  // we treat the bits just like they were vector's
1333          if (mode_current == MODE_FORWARD) iMinSAD +=  4 * lambda_vec16[iQuant];          if (mode_current == MODE_FORWARD) *Data->iMinSAD +=  4 * Data->lambda16 * 2;
1334          else iMinSAD +=  3 * lambda_vec16[iQuant];          else *Data->iMinSAD +=  3 * Data->lambda16 * 2;
1335    
1336            if (*Data->iMinSAD < *best_sad) {
1337          if (iMinSAD < *best_sad) {                  *best_sad = *Data->iMinSAD;
                 *best_sad = iMinSAD;  
1338                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1339                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1340                  pMB->pmvs[0].y = currentMV.y - predMV->y;                  pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1341                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = *(Data->currentMV+2) = *Data->currentMV;
1342                  else pMB->b_mvs[0] = currentMV;                  else pMB->b_mvs[0] = *(Data->currentMV+1) = *Data->currentMV; //we store currmv for interpolate search
1343          }          }
1344    
1345  }  }
# Line 1041  Line 1356 
1356                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1357                                  const int x, const int y,                                  const int x, const int y,
1358                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1359                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1360                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1361                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1362                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1363                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1364                                    SearchData * const Data)
1365    
1366  {  {
1367          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
         int32_t iMinSAD = 266*4096, skip_sad;  
1368          int k;          int k;
1369          VECTOR currentMV;  
1370          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
         SearchData Data;  
1371    
1372          Data.iMinSAD = &iMinSAD;          *Data->iMinSAD = 256*4096;
1373          Data.Cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;          Data->referencemv = b_mb->mvs;
         Data.iEdgedWidth = iEdgedWidth;  
         Data.currentMV = &currentMV;  
         Data.iQuant = iQuant;  
         Data.referencemv = b_mb->mvs;  
1374    
1375          Data.Ref= f_Ref->y + (x + iEdgedWidth*y) * 16;          Data->Ref = f_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1376          Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;          Data->RefH = f_RefH + (x + Data->iEdgedWidth*y) * 16;
1377          Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;          Data->RefV = f_RefV + (x + Data->iEdgedWidth*y) * 16;
1378          Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = f_RefHV + (x + Data->iEdgedWidth*y) * 16;
1379          Data.bRef = b_Ref->y + (x + iEdgedWidth*y) * 16;          Data->bRef = b_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1380          Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;          Data->bRefH = b_RefH + (x + Data->iEdgedWidth*y) * 16;
1381          Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;          Data->bRefV = b_RefV + (x + Data->iEdgedWidth*y) * 16;
1382          Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;          Data->bRefHV = b_RefHV + (x + Data->iEdgedWidth*y) * 16;
1383  /*  
1384  //What we do here is a complicated version of CheckCandidateDirect(0,0);          Data->max_dx = 2 * pParam->width - 2 * (x) * 16;
1385  get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16, pParam->width, pParam->height, 19);          Data->max_dy = 2 * pParam->height - 2 * (y) * 16;
1386            Data->min_dx = -(2 * 16 + 2 * (x) * 16);
1387  */          Data->min_dy = -(2 * 16 + 2 * (y) * 16);
         Data.max_dx = 2 * pParam->width - 2 * (x) * 16;  
         Data.max_dy = 2 * pParam->height - 2 * (y) * 16;  
         Data.min_dx = -(2 * 16 + 2 * (x) * 16);  
         Data.min_dy = -(2 * 16 + 2 * (y) * 16);  
1388    
1389          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1390                  pMB->mvs[k].x = Data.directmvF[k].x = ((TRB * Data.referencemv[k].x) / TRD);                  pMB->mvs[k].x = Data->directmvF[k].x = ((TRB * Data->referencemv[k].x) / TRD);
1391                  pMB->b_mvs[k].x = Data.directmvB[k].x = ((TRB - TRD) * Data.referencemv[k].x) / TRD;                  pMB->b_mvs[k].x = Data->directmvB[k].x = ((TRB - TRD) * Data->referencemv[k].x) / TRD;
1392                  pMB->mvs[k].y = Data.directmvF[k].y = ((TRB * Data.referencemv[k].y) / TRD);                  pMB->mvs[k].y = Data->directmvF[k].y = ((TRB * Data->referencemv[k].y) / TRD);
1393                  pMB->b_mvs[k].y = Data.directmvB[k].y = ((TRB - TRD) * Data.referencemv[k].y) / TRD;                  pMB->b_mvs[k].y = Data->directmvB[k].y = ((TRB - TRD) * Data->referencemv[k].y) / TRD;
1394    
1395                  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 )
1396                          || ( 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 )) {  
1397    
1398                          *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
1399                          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 1403 
1403                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1404                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1405                          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];
1406                          Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1407                          Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1408                          break;                          break;
1409                  }                  }
1410          }          }
# Line 1110  Line 1413 
1413                  CheckCandidate = CheckCandidateDirect;                  CheckCandidate = CheckCandidateDirect;
1414          else CheckCandidate = CheckCandidateDirectno4v;          else CheckCandidate = CheckCandidateDirectno4v;
1415    
1416          (*CheckCandidate)(0, 0, 255, &k, &Data);          (*CheckCandidate)(0, 0, 255, &k, Data);
1417    
1418  // skip decision  // skip decision
1419          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) {
1420                  //checking chroma. everything copied from MC                  //possible skip - checking chroma. everything copied from MC
1421                  //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
1422                  int sum, dx, dy, b_dx, b_dy;                  int sum, dx, dy, b_dx, b_dy;
1423    
# Line 1130  Line 1433 
1433                  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;
1434                  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));
1435    
1436                  sum = sad8bi(pCur->u + 8*x + 8*y*(iEdgedWidth/2),                  sum = sad8bi(pCur->u + 8*x + 8*y*(Data->iEdgedWidth/2),
1437                                          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,
1438                                          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,
1439                                          iEdgedWidth/2);                                          Data->iEdgedWidth/2);
1440                  sum += sad8bi(pCur->v + 8*x + 8*y*(iEdgedWidth/2),                  sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1441                                          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,
1442                                          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,
1443                                          iEdgedWidth/2);                                          Data->iEdgedWidth/2);
1444    
1445                  if ((uint32_t) sum < MAX_CHROMA_SAD_FOR_SKIP * Data.iQuant) {                  if (sum < MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) {
1446                          pMB->mode = MODE_DIRECT_NONE_MV;                          pMB->mode = MODE_DIRECT_NONE_MV;
1447                          return iMinSAD;                          return *Data->iMinSAD;
1448                  }                  }
1449          }          }
1450    
1451          skip_sad = iMinSAD;          skip_sad = *Data->iMinSAD;
1452    
1453  //  DIRECT MODE DELTA VECTOR SEARCH.  //  DIRECT MODE DELTA VECTOR SEARCH.
1454  //      This has to be made more effective, but at the moment I'm happy it's running at all  //      This has to be made more effective, but at the moment I'm happy it's running at all
# Line 1154  Line 1457 
1457                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1458                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1459    
1460          (*MainSearchPtr)(0, 0, &Data, 255);          (*MainSearchPtr)(0, 0, Data, 255);
1461    
1462          HalfpelRefine(&Data);          HalfpelRefine(Data);
1463    
1464          iMinSAD +=  1 * lambda_vec16[iQuant]; // one bit is needed to code direct mode. we treat this bit just like it was vector's          *Data->iMinSAD +=  1 * Data->lambda16 * 2; // one bit is needed to code direct mode
1465          *best_sad = iMinSAD;          *best_sad = *Data->iMinSAD;
1466    
1467          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1468                  pMB->mode = MODE_DIRECT;                  pMB->mode = MODE_DIRECT;
1469          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1470    
1471          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1472    
1473          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1474                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1475                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = ((Data->currentMV->x == 0)
1476                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1477                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          : pMB->mvs[k].x - Data->referencemv[k].x);
1478                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1479                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1480                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1481                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1482                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1483                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1484                          pMB->b_mvs[3] = pMB->b_mvs[2] = pMB->b_mvs[1] = pMB->b_mvs[0];                          pMB->b_mvs[3] = pMB->b_mvs[2] = pMB->b_mvs[1] = pMB->b_mvs[0];
1485                          break;                          break;
1486                  }                  }
1487          }          }
1488          return 0;//skip_sad;          return skip_sad;
1489  }  }
1490    
1491    
1492  static __inline void  static __inline void
1493  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const uint8_t * const f_Ref,
1494                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
# Line 1199  Line 1503 
1503                                  const uint32_t fcode,                                  const uint32_t fcode,
1504                                  const uint32_t bcode,                                  const uint32_t bcode,
1505                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1506                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1507                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1508                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1509                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1510                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1511                                    SearchData * const fData)
1512    
1513  {  {
 /* Interpolated MC motion vector search, this is tedious and more complicated because there are  
    two values for everything, always one for backward and one for forward ME. Still, we don't gain  
    much from this search, maybe it should simply be skipped and simply current i_sad16 value used  
    as "optimal". */  
1514    
1515          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1516    
1517          int iDirection, i, j;          int iDirection, i, j;
1518          int32_t iMinSAD = 256*4096;          SearchData bData;
         VECTOR currentMV[3];  
         SearchData fData, bData;  
   
         fData.iMinSAD = bData.iMinSAD = &iMinSAD;  
1519    
1520          fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          *(bData.iMinSAD = fData->iMinSAD) = 4096*256;
1521          fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;          bData.Cur = fData->Cur;
1522          fData.currentMV = currentMV; bData.currentMV = currentMV + 1;          fData->iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;
1523          fData.iQuant = bData.iQuant = iQuant;          bData.currentMV = fData->currentMV + 1;
1524          fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;          bData.lambda16 = fData->lambda16;
1525            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1526          bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  
1527          bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;          bData.bRef = fData->Ref = f_Ref + (x + y * iEdgedWidth) * 16;
1528          bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;          bData.bRefH = fData->RefH = f_RefH + (x + y * iEdgedWidth) * 16;
1529          bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;          bData.bRefV = fData->RefV = f_RefV + (x + y * iEdgedWidth) * 16;
1530          bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;          bData.bRefHV = fData->RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;
1531          bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;          bData.Ref = fData->bRef = b_Ref + (x + y * iEdgedWidth) * 16;
1532          bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;          bData.RefH = fData->bRefH = b_RefH + (x + y * iEdgedWidth) * 16;
1533          bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;          bData.RefV = fData->bRefV = b_RefV + (x + y * iEdgedWidth) * 16;
1534            bData.RefHV = fData->bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;
1535          bData.bpredMV = fData.predMV = *f_predMV;  
1536          fData.bpredMV = bData.predMV = *b_predMV;          bData.bpredMV = fData->predMV = *f_predMV;
1537            fData->bpredMV = bData.predMV = *b_predMV;
1538          currentMV[0] = pMB->mvs[0];  
1539          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
1540          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);
1541          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);
1542    
1543          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;
1544          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;
1545          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;
1546          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;
1547    
1548          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;
1549          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;
1550          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;
1551          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;
1552    
1553          CheckCandidateInt(currentMV[0].x, currentMV[0].y, 255, &iDirection, &fData);          CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
1554    
1555  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)
1556    
1557          do {          do {
1558                  iDirection = 255;                  iDirection = 255;
1559                  // forward MV moves                  // forward MV moves
1560                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
1561    
1562                  CheckCandidateInt(i + 1, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1563                  CheckCandidateInt(i, j + 1, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1564                  CheckCandidateInt(i - 1, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1565                  CheckCandidateInt(i, j - 1, 0, &iDirection, &fData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
1566    
1567                  // backward MV moves                  // backward MV moves
1568                  i = currentMV[1].x; j = currentMV[1].y;                  i = fData->currentMV[1].x; j = fData->currentMV[1].y;
1569                  currentMV[2] = currentMV[0];                  fData->currentMV[2] = fData->currentMV[0];
1570    
1571                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1572                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
# Line 1280  Line 1576 
1576          } while (!(iDirection));          } while (!(iDirection));
1577    
1578  // two bits are needed to code interpolate mode. we treat the bits just like they were vector's  // two bits are needed to code interpolate mode. we treat the bits just like they were vector's
1579          iMinSAD +=  2 * lambda_vec16[iQuant];          *fData->iMinSAD +=  2 * fData->lambda16 * 2;
1580          if (iMinSAD < *best_sad) {  
1581                  *best_sad = iMinSAD;          if (*fData->iMinSAD < *best_sad) {
1582                  pMB->mvs[0] = currentMV[0];                  *best_sad = *fData->iMinSAD;
1583                  pMB->b_mvs[0] = currentMV[1];                  pMB->mvs[0] = fData->currentMV[0];
1584                    pMB->b_mvs[0] = fData->currentMV[1];
1585                  pMB->mode = MODE_INTERPOLATE;                  pMB->mode = MODE_INTERPOLATE;
1586    
1587                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;
# Line 1294  Line 1591 
1591          }          }
1592  }  }
1593    
1594    
1595  void  void
1596  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
1597                                           FRAMEINFO * const frame,                                           FRAMEINFO * const frame,
# Line 1322  Line 1620 
1620          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1621          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
1622    
1623    // some pre-inintialized data for the rest of the search
1624    
1625            SearchData Data;
1626            int32_t iMinSAD;
1627            VECTOR currentMV[3];
1628            Data.iEdgedWidth = pParam->edged_width;
1629            Data.currentMV = currentMV;
1630            Data.iMinSAD = &iMinSAD;
1631            Data.lambda16 = lambda_vec16[frame->quant];
1632    
1633          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
1634    
1635          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
# Line 1332  Line 1640 
1640                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;
1641                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;
1642    
1643  /* special case, if collocated block is SKIPed: encoding is forward (0,0), cpb=0 without further ado */  /* special case, if collocated block is SKIPed in P-VOP: encoding is forward (0,0), cpb=0 without further ado */
1644                          if (b_mb->mode == MODE_NOT_CODED) {                          if ( (b_mb->mode == MODE_NOT_CODED) ) {
1645                                  pMB->mode = MODE_NOT_CODED;                                  pMB->mode = MODE_NOT_CODED;
1646                                  continue;                                  continue;
1647                          }                          }
1648    
1649                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
1650                            pMB->quant = frame->quant;
1651  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
1652          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
1653    
# Line 1346  Line 1656 
1656                                                                          &frame->image,                                                                          &frame->image,
1657                                                                          i, j,                                                                          i, j,
1658                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
1659                                                                          TRB, TRD,                                                                          TRB, TRD,
1660                                                                          pParam,                                                                          pParam,
1661                                                                          pMB, b_mb,                                                                          pMB, b_mb,
1662                                                                          &best_sad);                                                                          &best_sad,
1663                                                                            &Data);
1664    
1665                          if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                          if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1666    
# Line 1361  Line 1671 
1671                          SearchBF(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                          SearchBF(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
1672                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1673                                                  frame->motion_flags,                                                  frame->motion_flags,
1674                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
1675                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
1676                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
1677    
1678                          // backward search                          // backward search
1679                          SearchBF(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                          SearchBF(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
1680                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1681                                                  frame->motion_flags,                                                  frame->motion_flags,
1682                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
1683                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
1684                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
1685    
1686                          // interpolate search comes last, because it uses data from forward and backward as prediction                          // interpolate search comes last, because it uses data from forward and backward as prediction
1687    
# Line 1381  Line 1691 
1691                                                  i, j,                                                  i, j,
1692                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
1693                                                  frame->motion_flags,                                                  frame->motion_flags,
1694                                                  frame->quant, pParam,                                                  pParam,
1695                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
1696                                                  pMB, &best_sad);                                                  pMB, &best_sad,
1697                                                    &Data);
1698    
1699                          switch (pMB->mode) {                          switch (pMB->mode) {
1700                                  case MODE_FORWARD:                                  case MODE_FORWARD:
# Line 1416  Line 1727 
1727    
1728  /* Hinted ME starts here */  /* Hinted ME starts here */
1729    
1730  static __inline void  static void
1731  Search8hinted(  const SearchData * const OldData,  Search8hinted(  const SearchData * const OldData,
1732                                  const int x, const int y,                                  const int x, const int y,
1733                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1734                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1735                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1736                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1737                                  const int block)                          const int block,
1738                            SearchData * const Data)
1739  {  {
1740          SearchData Data;          int32_t temp_sad;
1741          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1742            Data->iMinSAD = OldData->iMinSAD + 1 + block;
1743            Data->currentMV = OldData->currentMV + 1 + block;
1744            Data->currentQMV = OldData->currentQMV + 1 + block;
1745            Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1746    
1747          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          if(pParam->m_quarterpel) {
1748          Data.iMinSAD = OldData->iMinSAD + 1 + block;                  Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1749          Data.currentMV = OldData->currentMV+1+block;                  if (block != 0) *(Data->iMinSAD) += Data->lambda8 *
1750          Data.iFcode = OldData->iFcode;                                                                          d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1751          Data.iQuant = OldData->iQuant;                                                                                                  Data->currentQMV->y - Data->predQMV.y,
1752                                                                                                    Data->iFcode);
1753          Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));                  CheckCandidate = CheckCandidate8Q;
1754          Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));          } else {
1755          Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  if (block != 0) *(Data->iMinSAD) += Data->lambda8 *
1756          Data.RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));                                                                          d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1757          Data.iEdgedWidth = pParam->edged_width;                                                                                                  Data->currentMV->y - Data->predMV.y,
1758          Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                                                                                                  Data->iFcode);
   
1759          CheckCandidate = CheckCandidate8;          CheckCandidate = CheckCandidate8;
1760            }
1761    
1762            Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));
1763            Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));
1764            Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1765            Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1766    
1767          if (block != 0)          Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
                 *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *  
                                                                 d_mv_bits(      Data.currentMV->x - Data.predMV.x,  
                                                                                         Data.currentMV->y - Data.predMV.y,  
                                                                                         Data.iFcode);  
1768    
1769            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1770                                    pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1771    
1772          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,          temp_sad = *(Data->iMinSAD); // store current MinSAD
                                 pParam->width, pParam->height, OldData->iFcode);  
   
         if (pMB->mode == MODE_INTER4V) {  
                 int dummy;  
                 CheckCandidate8(pMB->mvs[block].x, pMB->mvs[block].y, 0, &dummy, &Data); }  
1773    
1774          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1775                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1776                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1777    
1778          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1779    
1780            if(*(Data->iMinSAD) < temp_sad) {
1781                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1782                    Data->currentQMV->y = 2 * Data->currentMV->y;
1783            }
1784    
1785            if (MotionFlags & PMV_HALFPELREFINE8) {
1786                    temp_sad = *(Data->iMinSAD); // store current MinSAD
1787    
1788          if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                  HalfpelRefine(Data); // perform halfpel refine of current best vector
1789    
1790          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;                  if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1791          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;                          Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1792          pMB->mvs[block] = *(Data.currentMV);                          Data->currentQMV->y = 2 * Data->currentMV->y;
         pMB->sad8[block] =  4 * (*(Data.iMinSAD));  
1793  }  }
1794            }
1795    
1796            if(pParam->m_quarterpel) {
1797                    if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1798                            (MotionFlags & PMV_QUARTERPELREFINE8)) {
1799                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1800                                    pParam->width, pParam->height, Data->iFcode, 0);
1801                            CheckCandidate = CheckCandidate8_qpel;
1802                            QuarterpelRefine(Data);
1803                    }
1804            pMB->pmvs[block].x = Data->currentQMV->x - Data->predQMV.x;
1805            pMB->pmvs[block].y = Data->currentQMV->y - Data->predQMV.y;
1806            } else {
1807                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1808                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1809            }
1810    
1811            pMB->mvs[block] = *(Data->currentMV);
1812            pMB->qmvs[block] = *(Data->currentQMV);
1813    
1814            pMB->sad8[block] =  4 * (*Data->iMinSAD);
1815    }
1816    
1817  static void  static void
1818  SearchPhinted ( const uint8_t * const pRef,  SearchPhinted ( const uint8_t * const pRef,
# Line 1482  Line 1824 
1824                                  const int y,                                  const int y,
1825                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1826                                  const uint32_t iQuant,                                  const uint32_t iQuant,
                                 const uint32_t iFcode,  
1827                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1828                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1829                                  int inter4v,                                  int inter4v,
1830                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
1831                                    SearchData * const Data)
1832  {  {
1833    
1834          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1835    
1836          int i;          int i, t;
         VECTOR currentMV[5];  
         int32_t iMinSAD[5];  
         int32_t temp[5];  
1837          MainSearchFunc * MainSearchPtr;          MainSearchFunc * MainSearchPtr;
         SearchData Data;  
1838    
1839          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1840          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,
1841                                  pParam->width, pParam->height, iFcode);                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
1842    
1843          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->Cur = pCur->y + (x + y * iEdgedWidth) * 16;
1844          Data.iEdgedWidth = iEdgedWidth;          Data->Ref = pRef + (x + iEdgedWidth*y)*16;
1845          Data.currentMV = currentMV;          Data->RefH = pRefH + (x + iEdgedWidth*y) * 16;
1846          Data.iMinSAD = iMinSAD;          Data->RefV = pRefV + (x + iEdgedWidth*y) * 16;
1847          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data->RefHV = pRefHV + (x + iEdgedWidth*y) * 16;
1848          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->lambda16 = lambda_vec16[iQuant];
1849          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;  
1850    
1851          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
1852                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
1853                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
1854                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
1855                  Data.max_dy = EVEN(Data.max_dy);                  Data->max_dy = EVEN(Data->max_dy);
1856          }          }
1857    
1858          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;          for(i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
1859    
1860          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
1861    
1862          if (inter4v)          if(pParam->m_quarterpel) CheckCandidate = CheckCandidate16Q;
1863                  CheckCandidate = CheckCandidate16;          else
1864                    if (inter4v) CheckCandidate = CheckCandidate16;
1865          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
1866    
   
1867          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);
1868          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);
1869          if (pMB->mvs[0].x > Data.max_dx) pMB->mvs[0].x = Data.max_dx; // this is in case iFcode changed          if (pMB->mvs[0].x > Data->max_dx) pMB->mvs[0].x = Data->max_dx; // this is in case iFcode changed
1870          if (pMB->mvs[0].x < Data.min_dx) pMB->mvs[0].x = Data.min_dx;          if (pMB->mvs[0].x < Data->min_dx) pMB->mvs[0].x = Data->min_dx;
1871          if (pMB->mvs[0].y > Data.max_dy) pMB->mvs[0].y = Data.max_dy;          if (pMB->mvs[0].y > Data->max_dy) pMB->mvs[0].y = Data->max_dy;
1872          if (pMB->mvs[0].y < Data.min_dy) pMB->mvs[0].y = Data.min_dy;          if (pMB->mvs[0].y < Data->min_dy) pMB->mvs[0].y = Data->min_dy;
1873    
1874          CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);          (*CheckCandidate)(pMB->mvs[0].x, pMB->mvs[0].y, 0, &t, Data);
1875    
1876          if (pMB->mode == MODE_INTER4V)          if (pMB->mode == MODE_INTER4V)
1877                  for (i = 1; i < 4; i++) { // all four vectors will be used as four predictions for 16x16 search                  for (i = 1; i < 4; i++) { // all four vectors will be used as four predictions for 16x16 search
1878                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);
1879                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);
1880                          if (!(make_mask(pMB->mvs, i)))                          if (!(make_mask(pMB->mvs, i)))
1881                                  CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);                                  (*CheckCandidate)(pMB->mvs[i].x, pMB->mvs[i].y, 0, &t, Data);
1882                  }                  }
1883    
1884          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1553  Line 1887 
1887                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1888                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1889    
1890          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1891    
1892          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1893    
1894            for(i = 0; i < 5; i++) {
1895                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1896                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1897            }
1898    
1899            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1900                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1901                                    pParam->width, pParam->height, Data->iFcode, 0);
1902                    CheckCandidate = CheckCandidate16_qpel;
1903                    QuarterpelRefine(Data);
1904            }
1905    
1906          if (inter4v)          if (inter4v) {
1907                  for(i = 0; i < 4; i++)                  SearchData Data8;
1908                          Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                  Data8.iFcode = Data->iFcode;
1909                    Data8.lambda8 = Data->lambda8;
1910                    Data8.iEdgedWidth = Data->iEdgedWidth;
1911                    Data8.RefQ = Data->RefQ;
1912                    Search8hinted(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1913                    Search8hinted(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1914                    Search8hinted(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1915                    Search8hinted(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1916            }
1917    
1918          if (!(inter4v) ||          if (!(inter4v) ||
1919                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3] +
1920                                                            Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1921  // INTER MODE  // INTER MODE
   
1922                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1923                  pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1924                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1925    
1926                    pMB->qmvs[0] = pMB->qmvs[1]
1927                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1928    
1929                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1930                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1931    
1932                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1933                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predQMV.x;
1934                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predQMV.y;
1935                    }
1936                    else {
1937                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1938                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1939                    }
1940          } else {          } else {
1941  // INTER4V MODE; all other things are already set in Search8hinted  // INTER4V MODE; all other things are already set in Search8hinted
1942                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1943                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3]
1944                                                    + Data->iMinSAD[4] + IMV16X16 * iQuant;
1945          }          }
1946    
1947  }  }
# Line 1595  Line 1959 
1959          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
1960    
1961          uint32_t x, y;          uint32_t x, y;
1962            uint8_t * qimage;
1963            int32_t temp[5], quant = current->quant;
1964            int32_t iMinSAD[5];
1965            VECTOR currentMV[5], currentQMV[5];
1966            SearchData Data;
1967            Data.iEdgedWidth = pParam->edged_width;
1968            Data.currentMV = currentMV;
1969            Data.currentQMV = currentQMV;
1970            Data.iMinSAD = iMinSAD;
1971            Data.temp = temp;
1972            Data.iFcode = current->fcode;
1973            Data.rounding = pParam->m_rounding_type;
1974    
1975            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
1976                    return; // allocate some mem for qpel interpolated blocks
1977                                      // somehow this is dirty since I think we shouldn't use malloc outside
1978                                      // encoder_create() - so please fix me!
1979    
1980            Data.RefQ = qimage;
1981    
1982          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
1983    
# Line 1606  Line 1989 
1989  //intra mode is copied from the first pass. At least for the time being  //intra mode is copied from the first pass. At least for the time being
1990                          if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;                          if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;
1991    
1992    
1993                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
1994                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
1995                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant; }
1996                            else {
1997                                    if (pMB->dquant != NO_CHANGE) {
1998                                            quant += DQtab[pMB->dquant];
1999                                            if (quant > 31) quant = 31;
2000                                            else if (quant < 1) quant = 1;
2001                                    }
2002                                    pMB->quant = quant;
2003                            }
2004    
2005                          SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
2006                                                          y, current->motion_flags, pMB->quant,                                                          y, current->motion_flags, pMB->quant,
2007                                                          current->fcode, pParam, pMBs,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
2008                                                          current->global_flags & XVID_INTER4V, pMB);                                                          &Data);
2009    
2010                  }                  }
2011          }          }
2012            free(qimage);
2013  }  }
2014    
2015  static __inline int  static __inline int
# Line 1624  Line 2017 
2017                                  const uint8_t * const pCur,                                  const uint8_t * const pCur,
2018                                  const int x,                                  const int x,
2019                                  const int y,                                  const int y,
                                 const uint32_t iFcode,  
2020                                  const MBParam * const pParam,                                  const MBParam * const pParam,
2021                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
2022                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
2023                                    SearchData * const Data)
2024  {  {
2025    
2026          const int32_t iEdgedWidth = pParam->edged_width;          int i = 255, mask;
2027          int i, mask;          VECTOR pmv[3];
         VECTOR currentMV, pmv[3];  
         int32_t iMinSAD = MV_MAX_ERROR;  
         SearchData Data;  
2028    
2029          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          *(Data->iMinSAD) = MV_MAX_ERROR;
2030          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);
2031                                  pParam->width, pParam->height, iFcode);          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2032                                    pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
2033    
2034          Data.Cur = pCur + (x + y * iEdgedWidth) * 16;          Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
2035          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;  
2036    
2037          CheckCandidate = CheckCandidate16no4vI;          CheckCandidate = CheckCandidate16no4vI;
2038    
2039          pmv[1].x = EVEN(pMB->mvs[0].x);          pmv[1].x = EVEN(pMB->mvs[0].x);
2040          pmv[1].y = EVEN(pMB->mvs[0].y);          pmv[1].y = EVEN(pMB->mvs[0].y);
2041          pmv[0].x = EVEN(Data.predMV.x);          pmv[0].x = EVEN(Data->predMV.x);
2042          pmv[0].y = EVEN(Data.predMV.y);          pmv[0].y = EVEN(Data->predMV.y);
2043          pmv[2].x = pmv[2].y = 0;          pmv[2].x = pmv[2].y = 0;
2044    
2045          CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, &Data);          CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, Data);
2046          if (!(mask = make_mask(pmv, 1)))          if (!(mask = make_mask(pmv, 1)))
2047                  CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, &Data);                  CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, Data);
2048          if (!(mask = make_mask(pmv, 2)))          if (!(mask = make_mask(pmv, 2)))
2049                  CheckCandidate16no4vI(0, 0, mask, &i, &Data);                  CheckCandidate16no4vI(0, 0, mask, &i, Data);
2050    
2051          DiamondSearch(currentMV.x, currentMV.y, &Data, i);          DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
2052    
2053          pMB->mvs[0] = pMB->mvs[1]          pMB->mvs[0] = *Data->currentMV;
                         = pMB->mvs[2] = pMB->mvs[3] = currentMV; // all, for future get_pmv()  
2054    
2055          return iMinSAD;          return *(Data->iMinSAD);
2056  }  }
2057    
2058  #define INTRA_THRESH    1350  #define INTRA_THRESH    1350
# Line 1683  Line 2068 
2068          uint32_t x, y, intra = 0;          uint32_t x, y, intra = 0;
2069          int sSAD = 0;          int sSAD = 0;
2070    
2071            VECTOR currentMV;
2072            int32_t iMinSAD;
2073            SearchData Data;
2074            Data.iEdgedWidth = pParam->edged_width;
2075            Data.currentMV = &currentMV;
2076            Data.iMinSAD = &iMinSAD;
2077            Data.iFcode = iFcode;
2078    
2079          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
2080    
2081          for (y = 0; y < pParam->mb_height-1; y++) {          for (y = 1; y < pParam->mb_height-1; y++) {
2082                  for (x = 0; x < pParam->mb_width; x++) {                  for (x = 1; x < pParam->mb_width-1; x++) {
2083                          int sad, dev;                          int sad, dev;
   
2084                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2085    
2086                          sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,                          sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
2087                                                                  iFcode, pParam, pMBs, pMB);                                                                  pParam, pMBs, pMB, &Data);
2088    
                         if ( x != 0 && y != 0 && x != pParam->mb_width-1 ) { //no edge macroblocks, they just don't work  
2089                                  if (sad > INTRA_THRESH) {                                  if (sad > INTRA_THRESH) {
2090                                          dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                          dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
2091                                                                    pParam->edged_width);                                                                    pParam->edged_width);
# Line 1703  Line 2094 
2094                                  }                                  }
2095                                  sSAD += sad;                                  sSAD += sad;
2096                          }                          }
   
                 }  
2097          }          }
2098          sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);          sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2099          if (sSAD > INTER_THRESH ) return 1; //P frame          if (sSAD > INTER_THRESH ) return 1; //P frame
# Line 1712  Line 2101 
2101          return 0; // B frame          return 0; // B frame
2102    
2103  }  }
2104    
2105    int
2106    FindFcode(      const MBParam * const pParam,
2107                            const FRAMEINFO * const current)
2108    {
2109            uint32_t x, y;
2110            int max = 0, min = 0, i;
2111    
2112            for (y = 0; y < pParam->mb_height; y++) {
2113                    for (x = 0; x < pParam->mb_width; x++) {
2114    
2115                            MACROBLOCK *pMB = &current->mbs[x + y * pParam->mb_width];
2116                            for(i = 0; i < (pMB->mode == MODE_INTER4V ? 4:1); i++) {
2117                                    if (pMB->mvs[i].x > max) max = pMB->mvs[i].x;
2118                                    if (pMB->mvs[i].y > max) max = pMB->mvs[i].y;
2119    
2120                                    if (pMB->mvs[i].x < min) min = pMB->mvs[i].x;
2121                                    if (pMB->mvs[i].y < min) min = pMB->mvs[i].y;
2122                            }
2123                    }
2124            }
2125    
2126            min = -min;
2127            max += 1;
2128            if (min > max) max = min;
2129            if (pParam->m_quarterpel) max *= 2;
2130    
2131            for (i = 1; (max > 32 << (i - 1)); i++);
2132            return i;
2133    }
2134    
2135    
2136    /* Global Motion Estimation, (C) 2002 by sysKin */
2137    /* calculate global translation from local (halfpel) motion field */
2138    
2139    static VECTOR
2140    GlobalMotionEst(const MACROBLOCK * const pMBs, const MBParam * const pParam, const uint32_t iFcode)
2141    {
2142    
2143            int count, bestcount = 0;
2144            int x, y;
2145            VECTOR gmc;
2146            int step, min_x, max_x, min_y, max_y;
2147            uint32_t mx, my;
2148    
2149            min_x = min_y = -32<<iFcode;
2150            max_x = max_y = 32<<iFcode;
2151    
2152            for (step = 32; step >= 2; step /= 2) {
2153                    bestcount = 0;
2154                    for (y = min_y; y <= max_y; y += step)
2155                            for (x = min_x ; x <= max_x; x += step) {
2156                                    count = 0;
2157                                    //for all macroblocks
2158                                    for (my = 1; my < pParam->mb_height-1; my++)
2159                                            for (mx = 1; mx < pParam->mb_width-1; mx++) {
2160                                                    const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2161                                                    VECTOR mv;
2162    
2163                                                    if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
2164                                                            continue;
2165    
2166                                                    mv = pMB->mvs[0];
2167                                                    if ( ABS(mv.x - x) <= step && ABS(mv.y - y) <= step )   /* GMC translation is always halfpel-res */
2168                                                            count++;
2169                                            }
2170                                    if (count >= bestcount) { bestcount = count; gmc.x = x; gmc.y = y; }
2171                            }
2172                    min_x = gmc.x - step;
2173                    max_x = gmc.x + step;
2174                    min_y = gmc.y - step;
2175                    max_y = gmc.y + step;
2176    
2177            }
2178            if (pParam->m_quarterpel) {
2179                    gmc.x *= 2;
2180                    gmc.y *= 2;     /* we store the halfpel value as pseudo-qpel to make comparison easier */
2181            }
2182    
2183            if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10)
2184                    gmc.x = gmc.y = 0; //no camara pan, no GMC
2185    
2186            return gmc;
2187    }

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

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