[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 601, Thu Oct 17 13:50:23 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]) {          if (data->temp[0] < data->iMinSAD[0]) {
118                  data->iMinSAD[0] = data->temp[0];                  data->iMinSAD[0] = data->temp[0];
# Line 137  Line 147 
147                  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;
148          }          }
149    
150          sad = lambda_vec16[data->iQuant] *          sad = data->lambda16 * d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
151                          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);  
152    
153          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
154                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 148  Line 157 
157  }  }
158    
159  static void  static void
160  CheckCandidate16no4vI(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidate16_qpel(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
161    
162    // CheckCandidate16 variant which expects x and y in quarter pixel resolution
163    // Important: This is no general usable routine! x and y must be +/-1 (qpel resolution!)
164    // around currentMV!
165    {
166            int t;
167            uint8_t * Reference = (uint8_t *)data->RefQ;
168            const uint8_t *ref1, *ref2, *ref3, *ref4;
169            VECTOR halfpelMV = *(data->currentMV);
170    
171            int32_t iEdgedWidth = data->iEdgedWidth;
172            uint32_t rounding = data->rounding;
173    
174            if (( x > data->max_dx) || ( x < data->min_dx)
175                    || ( y > data->max_dy) || (y < data->min_dy)) return;
176    
177            switch( ((x&1)<<1) + (y&1) )
178            {
179            case 0: // pure halfpel position - shouldn't happen during a refinement step
180                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, Reference);
181                    break;
182    
183            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
184                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
185                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
186    
187                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
188                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding);
189                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding);
190                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding);
191                    break;
192    
193            case 2: // x qpel, y halfpel - left or right during qpel refinement
194                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
195                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref2);
196    
197                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
198                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding);
199                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding);
200                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding);
201                    break;
202    
203            default: // x and y in qpel resolution - the "corners" (top left/right and
204                             // bottom left/right) during qpel refinement
205                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
206                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
207                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref3);
208                    GET_REFERENCE(x - halfpelMV.x, y - halfpelMV.y, ref4);
209    
210                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
211                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
212                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
213                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
214                    break;
215            }
216    
217            data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp+1);
218    
219            t = d_mv_bits(x - data->predQMV.x, y - data->predQMV.y, data->iFcode);
220            data->temp[0] += data->lambda16 * t;
221            data->temp[1] += data->lambda8 * t;
222    
223            if (data->temp[0] < data->iMinSAD[0]) {
224                    data->iMinSAD[0] = data->temp[0];
225                    data->currentQMV[0].x = x; data->currentQMV[0].y = y;
226            /*      *dir = Direction;*/ }
227    
228            if (data->temp[1] < data->iMinSAD[1]) {
229                    data->iMinSAD[1] = data->temp[1]; data->currentQMV[1].x = x; data->currentQMV[1].y = y; }
230            if (data->temp[2] < data->iMinSAD[2]) {
231                    data->iMinSAD[2] = data->temp[2]; data->currentQMV[2].x = x; data->currentQMV[2].y = y; }
232            if (data->temp[3] < data->iMinSAD[3]) {
233                    data->iMinSAD[3] = data->temp[3]; data->currentQMV[3].x = x; data->currentQMV[3].y = y; }
234            if (data->temp[4] < data->iMinSAD[4]) {
235                    data->iMinSAD[4] = data->temp[4]; data->currentQMV[4].x = x; data->currentQMV[4].y = y; }
236    }
237    
238    static void
239    CheckCandidate16no4v_qpel(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
240    
241    // CheckCandidate16no4v variant which expects x and y in quarter pixel resolution
242    // Important: This is no general usable routine! x and y must be +/-1 (qpel resolution!)
243    // around currentMV!
244  {  {
245          int32_t sad;          int32_t sad;
246            uint8_t * Reference = (uint8_t *) data->RefQ;
247            const uint8_t *ref1, *ref2, *ref3, *ref4;
248            VECTOR halfpelMV = *(data->currentMV);
249    
250            int32_t iEdgedWidth = data->iEdgedWidth;
251            uint32_t rounding = data->rounding;
252    
253          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
254                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
255    
256          sad = lambda_vec16[data->iQuant] *          switch( ((x&1)<<1) + (y&1) )
257                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          {
258            case 0: // pure halfpel position - shouldn't happen during a refinement step
259                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, Reference);
260                    break;
261    
262            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
263                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
264                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
265    
266                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
267                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding);
268                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding);
269                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding);
270                    break;
271    
272          sad += sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),          case 2: // x qpel, y halfpel - left or right during qpel refinement
273                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
274                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref2);
275    
276                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
277                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding);
278                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding);
279                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding);
280                    break;
281    
282            default: // x and y in qpel resolution - the "corners" (top left/right and
283                             // bottom left/right) during qpel refinement
284                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
285                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
286                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref3);
287                    GET_REFERENCE(x - halfpelMV.x, y - halfpelMV.y, ref4);
288    
289                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
290                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
291                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
292                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
293                    break;
294            }
295    
296            sad = data->lambda16 *
297                            d_mv_bits(x - data->predQMV.x, y - data->predQMV.y, data->iFcode);
298            sad += sad16(data->Cur, Reference, data->iEdgedWidth, MV_MAX_ERROR);
299    
300            if (sad < *(data->iMinSAD)) {
301                    *(data->iMinSAD) = sad;
302                    data->currentQMV[0].x = x; data->currentQMV[0].y = y;
303    //              *dir = Direction;
304            }
305    }
306    
307    static void
308    CheckCandidate16no4vI(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
309    {
310            int32_t sad;
311    
312            if (( x > data->max_dx) || ( x < data->min_dx)
313                    || ( y > data->max_dy) || (y < data->min_dy)) return;
314    
315            sad = sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),
316                                          data->iEdgedWidth, 256*4096);                                          data->iEdgedWidth, 256*4096);
317    
318          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
# Line 193  Line 347 
347                  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;
348          }          }
349    
350          sad = lambda_vec16[data->iQuant] *          sad = data->lambda16 *
351                          ( 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) +
352                            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) );
353    
# Line 216  Line 370 
370    
371          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
372    
373          sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);          sad = data->lambda16 * d_mv_bits(x, y, 1);
374    
375          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
376                  mvs.x = data->directmvF[k].x + x;                  mvs.x = data->directmvF[k].x + x;
# Line 269  Line 423 
423          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
424          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
425    
426          if (( x > 31) || ( x < -31) || ( y > 31) || (y < -31)) return;          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
427    
428                  sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);                  sad = data->lambda16 * d_mv_bits(x, y, 1);
429    
430          mvs.x = data->directmvF[0].x + x;          mvs.x = data->directmvF[0].x + x;
431          b_mvs.x = ((x == 0) ?          b_mvs.x = ((x == 0) ?
# Line 328  Line 482 
482          }          }
483    
484          sad = sad8(data->Cur, Reference, data->iEdgedWidth);          sad = sad8(data->Cur, Reference, data->iEdgedWidth);
485          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);
486    
487          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
488                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 336  Line 490 
490                  *dir = Direction; }                  *dir = Direction; }
491  }  }
492    
493    static void
494    CheckCandidate8_qpel(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
495    // CheckCandidate16no4v variant which expects x and y in quarter pixel resolution
496    // Important: This is no general usable routine! x and y must be +/-1 (qpel resolution!)
497    // around currentMV!
498    
499    {
500            int32_t sad;
501            uint8_t *Reference = (uint8_t *) data->RefQ;
502            const uint8_t *ref1, *ref2, *ref3, *ref4;
503            VECTOR halfpelMV = *(data->currentMV);
504    
505            int32_t iEdgedWidth = data->iEdgedWidth;
506            uint32_t rounding = data->rounding;
507    
508            if (( x > data->max_dx) || ( x < data->min_dx)
509                    || ( y > data->max_dy) || (y < data->min_dy)) return;
510    
511            switch( ((x&1)<<1) + (y&1) )
512            {
513            case 0: // pure halfpel position - shouldn't happen during a refinement step
514                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, Reference);
515                    break;
516    
517            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
518                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
519                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
520    
521                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
522                    break;
523    
524            case 2: // x qpel, y halfpel - left or right during qpel refinement
525                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
526                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref2);
527    
528                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
529                    break;
530    
531            default: // x and y in qpel resolution - the "corners" (top left/right and
532                             // bottom left/right) during qpel refinement
533                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
534                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
535                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref3);
536                    GET_REFERENCE(x - halfpelMV.x, y - halfpelMV.y, ref4);
537    
538                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
539                    break;
540            }
541    
542            sad = sad8(data->Cur, Reference, data->iEdgedWidth);
543            sad += data->lambda8 * d_mv_bits(x - data->predQMV.x, y - data->predQMV.y, data->iFcode);
544    
545            if (sad < *(data->iMinSAD)) {
546                    *(data->iMinSAD) = sad;
547                    data->currentQMV->x = x; data->currentQMV->y = y;
548                    *dir = Direction; }
549    }
550    
551  /* CHECK_CANDIATE FUNCTIONS END */  /* CHECK_CANDIATE FUNCTIONS END */
552    
553  /* MAINSEARCH FUNCTIONS START */  /* MAINSEARCH FUNCTIONS START */
# Line 504  Line 716 
716          CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);          CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);
717  }  }
718    
719    
720    static void
721    QuarterpelRefine(const SearchData * const data)
722    {
723    /* Perform quarter pixel refinement*/
724    
725            VECTOR backupMV = *(data->currentQMV);
726            int iDirection; //not needed
727    
728            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);
729            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);
730            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);
731            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y + 1, 0);
732    
733            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y, 0);
734            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y, 0);
735    
736            CHECK_CANDIDATE(backupMV.x, backupMV.y + 1, 0);
737            CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);
738    
739    }
740    
741  static __inline int  static __inline int
742  SkipDecisionP(const IMAGE * current, const IMAGE * reference,  SkipDecisionP(const IMAGE * current, const IMAGE * reference,
743                                                          const int x, const int y,                                                          const int x, const int y,
# Line 517  Line 751 
751          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,
752                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);
753          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
754          sadC += sad8(current->v + x*8 + y*(iEdgedWidth/2)*8,          sadC += sad8(current->v + (x + y*(iEdgedWidth/2))*8,
755                                          reference->v + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                          reference->v + (x + y*(iEdgedWidth/2))*8, iEdgedWidth/2);
756          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
757    
758          return 1;          return 1;
# Line 530  Line 764 
764          pMB->mode = MODE_NOT_CODED;          pMB->mode = MODE_NOT_CODED;
765          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;
766          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;
767    
768            pMB->qmvs[0].x = pMB->qmvs[1].x = pMB->qmvs[2].x = pMB->qmvs[3].x = 0;
769            pMB->qmvs[0].y = pMB->qmvs[1].y = pMB->qmvs[2].y = pMB->qmvs[3].y = 0;
770    
771          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;
772  }  }
773    
# Line 550  Line 788 
788    
789          uint32_t x, y;          uint32_t x, y;
790          uint32_t iIntra = 0;          uint32_t iIntra = 0;
791          int32_t InterBias;          int32_t InterBias, quant = current->quant;
792            uint8_t *qimage;
793    
794          // some pre-initialized thingies for SearchP          // some pre-initialized thingies for SearchP
795          int32_t temp[5];          int32_t temp[5];
796          VECTOR currentMV[5];          VECTOR currentMV[5];
797            VECTOR currentQMV[5];
798          int32_t iMinSAD[5];          int32_t iMinSAD[5];
799          SearchData Data;          SearchData Data;
800          Data.iEdgedWidth = pParam->edged_width;          Data.iEdgedWidth = pParam->edged_width;
801          Data.currentMV = currentMV;          Data.currentMV = currentMV;
802            Data.currentQMV = currentQMV;
803          Data.iMinSAD = iMinSAD;          Data.iMinSAD = iMinSAD;
804          Data.temp = temp;          Data.temp = temp;
805          Data.iFcode = current->fcode;          Data.iFcode = current->fcode;
806            Data.rounding = pParam->m_rounding_type;
807    
808            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
809                    return 1; // allocate some mem for qpel interpolated blocks
810                                      // somehow this is dirty since I think we shouldn't use malloc outside
811                                      // encoder_create() - so please fix me!
812    
813          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
814    
# Line 576  Line 823 
823    
824                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
825                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
826                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant;
827                            } else {
828                                    if (pMB->dquant != NO_CHANGE) {
829                                            quant += DQtab[pMB->dquant];
830                                            if (quant > 31) quant = 31;
831                                            else if (quant < 1) quant = 1;
832                                    }
833                                    pMB->quant = quant;
834                            }
835    
836  //initial skip decision  //initial skip decision
837    
838                          if ((pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)                          if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * INITIAL_SKIP_THRESH)
839                                  && (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) ) {                                  if (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
                                 if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {  
840                                                  SkipMacroblockP(pMB, sad00);                                                  SkipMacroblockP(pMB, sad00);
841                                                  continue;                                                  continue;
842                                  }                                  }
                         } else sad00 = 256*4096; // skip not allowed - for final skip decision  
843    
844                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, qimage, pCurrent, x,
845                                                  y, current->motion_flags, pMB->quant,                                                  y, current->motion_flags, pMB->quant,
846                                                  &Data, pParam, pMBs, reference->mbs,                                                  &Data, pParam, pMBs, reference->mbs,
847                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
848    
849  /* 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?" */
850                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)                          if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * MAX_SAD00_FOR_SKIP
851                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)                                  && ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH) )
852                                  { SkipMacroblockP(pMB, sad00); continue; }                                  if (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
853                                            SkipMacroblockP(pMB, sad00);
854                                            continue;
855                                    }
856    
857  /* finally, intra decision */  /* finally, intra decision */
858    
# Line 613  Line 869 
869                                                    pParam->edged_width);                                                    pParam->edged_width);
870    
871                                  if (deviation < (pMB->sad16 - InterBias)) {                                  if (deviation < (pMB->sad16 - InterBias)) {
872                                          if (++iIntra >= iLimit) return 1;                                          if (++iIntra >= iLimit) { free(qimage); return 1; }
873                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
874                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
875                                                          pMB->mvs[3] = zeroMV;                                                          pMB->mvs[3] = zeroMV;
876                                            pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] =
877                                                            pMB->qmvs[3] = zeroMV;
878                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
879                                                  pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
880                                  }                                  }
881                          }                          }
882                  }                  }
883          }          }
884            free(qimage);
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 700  Line 960 
960          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
961          VECTOR pmv[7];          VECTOR pmv[7];
962    
963            Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
964    
965          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)()
966          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,
967                                  pParam->width, pParam->height, Data->iFcode);                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
968    
969          Data->predMV = pmv[0];          Data->predMV = pmv[0];
970    
971          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
972          Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;          Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;
973          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
974          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
975          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
976            Data->RefQ = pRefQ;
977    
978          Data->iQuant = iQuant;          Data->lambda16 = lambda_vec16[iQuant];
979    
980          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
981                  Data->min_dx = EVEN(Data->min_dx);                  Data->min_dx = EVEN(Data->min_dx);
# Line 719  Line 983 
983                  Data->min_dy = EVEN(Data->min_dy);                  Data->min_dy = EVEN(Data->min_dy);
984                  Data->max_dy = EVEN(Data->max_dy); }                  Data->max_dy = EVEN(Data->max_dy); }
985    
986          for(i = 0;  i < 5; i++) Data->iMinSAD[i] = 256*4096;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
987    
988          if (inter4v) CheckCandidate = CheckCandidate16;          if (inter4v) CheckCandidate = CheckCandidate16;
989          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
990    
991          (*CheckCandidate)(Data->predMV.x, Data->predMV.y, 0, &iDirection, Data);          for(i = 0;  i < 5; i++)
992                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
         for(i = 0;  i < 5; i++) Data->currentMV[i].x = Data->currentMV[i].y = 0;  
993    
994          i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);          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;
# Line 735  Line 998 
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 (inter4v) CheckCandidate = CheckCandidate16;
1011            else CheckCandidate = CheckCandidate16no4v;
1012    
1013    
1014  /* main loop. checking all predictions */  /* main loop. checking all predictions */
1015    
1016          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
1017                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1018                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, Data);                  (*CheckCandidate)(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1019                  if (Data->iMinSAD[0] <= threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1020          }          }
1021    
# Line 803  Line 1068 
1068    
1069          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1070    
1071            for(i = 0; i < 5; i++) {
1072                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1073                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1074            }
1075    
1076            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1077    
1078                    if(inter4v)
1079                            CheckCandidate = CheckCandidate16_qpel;
1080                    else
1081                            CheckCandidate = CheckCandidate16no4v_qpel;
1082    
1083                            Data->iMinSAD[0] -= lambda_vec16[iQuant] *
1084                                    d_mv_bits(Data->predMV.x - Data->currentMV[0].x, Data->predMV.y - Data->currentMV[0].y, Data->iFcode);
1085                            Data->iMinSAD[1] -= lambda_vec8[iQuant] *
1086                                    d_mv_bits(Data->predMV.x - Data->currentMV[1].x, Data->predMV.y - Data->currentMV[1].y, Data->iFcode);
1087    
1088                            Data->iMinSAD[0] += lambda_vec16[iQuant] *
1089                                    d_mv_bits(Data->predQMV.x - Data->currentQMV[0].x, Data->predMV.y - Data->currentQMV[0].y, Data->iFcode);
1090                            Data->iMinSAD[1] += lambda_vec8[iQuant] *
1091                                    d_mv_bits(Data->predQMV.x - Data->currentQMV[1].x, Data->predMV.y - Data->currentQMV[1].y, Data->iFcode);
1092    
1093                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1094                                    pParam->width, pParam->height, Data->iFcode, 0);
1095    
1096                    QuarterpelRefine(Data);
1097            }
1098    
1099          if (inter4v) {          if (inter4v) {
1100                  SearchData Data8;                  SearchData Data8;
1101                  Data8.iFcode = Data->iFcode;                  Data8.iFcode = Data->iFcode;
1102                  Data8.iQuant = Data->iQuant;                  Data8.lambda8 = lambda_vec8[iQuant];
1103                  Data8.iEdgedWidth = Data->iEdgedWidth;                  Data8.iEdgedWidth = Data->iEdgedWidth;
1104                  Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);                  Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1105                  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);
# Line 822  Line 1115 
1115                  pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1116                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1117    
1118                    pMB->qmvs[0] = pMB->qmvs[1]
1119                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1120    
1121                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1122                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1123    
1124                    if(pParam->m_quarterpel) {
1125                            pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predQMV.x;
1126                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predQMV.y;
1127                    }
1128                    else {
1129                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1130                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1131                    }
1132          } else {          } else {
1133  // INTER4V MODE; all other things are already set in Search8  // INTER4V MODE; all other things are already set in Search8
1134                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1135                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1136                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1137          }          }
   
1138  }  }
1139    
1140  static void  static void
# Line 847  Line 1148 
1148                  SearchData * const Data)                  SearchData * const Data)
1149  {  {
1150          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1151            Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1152          Data->iMinSAD = OldData->iMinSAD + 1 + block;          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1153          Data->currentMV = OldData->currentMV + 1 + block;          Data->currentMV = OldData->currentMV + 1 + block;
1154            Data->currentQMV = OldData->currentQMV + 1 + block;
1155    
1156            if(pParam->m_quarterpel) {
1157                    //it is qpel. substract d_mv_bits[qpel] from 0, add d_mv_bits[hpel] everywhere
1158                    if (block == 0)
1159                            *(Data->iMinSAD) -= Data->lambda8 *
1160                                                                            d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1161                                                                                                    Data->currentQMV->y - Data->predQMV.y,
1162                                                                                                    Data->iFcode);
1163    
1164          if (block != 0)                  *(Data->iMinSAD) += Data->lambda8 *
1165                  *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *                                                                          d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1166                                                                                                    Data->currentMV->y - Data->predMV.y,
1167                                                                                                    Data->iFcode);
1168            } else //it is not qpel. add d_mv_bits[hpel] everywhere but not in 0 (it's already there)
1169                    if (block != 0) *(Data->iMinSAD) += Data->lambda8 *
1170                                                                  d_mv_bits(      Data->currentMV->x - Data->predMV.x,                                                                  d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1171                                                                                          Data->currentMV->y - Data->predMV.y,                                                                                          Data->currentMV->y - Data->predMV.y,
1172                                                                                          Data->iFcode);                                                                                          Data->iFcode);
1173    
1174    
1175          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
1176    
1177                  Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));
1178                  Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));
1179                  Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1180                  Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1181                    Data->RefQ = OldData->RefQ;
1182    
1183                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
1184    
1185                  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,
1186                                  pParam->width, pParam->height, OldData->iFcode);                                  pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1187    
1188                  CheckCandidate = CheckCandidate8;                  CheckCandidate = CheckCandidate8;
1189    
1190                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & PMV_EXTSEARCH8) {
1191                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1192    
1193                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1194                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1195                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1196                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1197    
1198                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);    }                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1199    
1200                            if(*(Data->iMinSAD) < temp_sad) {
1201                                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1202                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1203                            }
1204                    }
1205    
1206                    if (MotionFlags & PMV_HALFPELREFINE8) {
1207                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1208    
1209                            HalfpelRefine(Data); // perform halfpel refine of current best vector
1210    
1211                            if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1212                                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1213                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1214                            }
1215                    }
1216    
1217                    if(pParam->m_quarterpel) {
1218                            if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1219                                    (MotionFlags & PMV_QUARTERPELREFINE8)) {
1220    
1221                            CheckCandidate = CheckCandidate8_qpel;
1222                            Data->iMinSAD[0] -= Data->lambda8 *
1223                                            d_mv_bits(Data->predMV.x - Data->currentMV[0].x, Data->predMV.y - Data->currentMV[0].y, Data->iFcode);
1224    
1225                            Data->iMinSAD[0] += Data->lambda8 *
1226                                    d_mv_bits(Data->predQMV.x - Data->currentQMV[0].x, Data->predQMV.y - Data->currentQMV[0].y, Data->iFcode);
1227    
1228                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(Data);                                  QuarterpelRefine(Data);
1229                            }
1230                    }
1231          }          }
1232    
1233            if(pParam->m_quarterpel) {
1234                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predQMV.x;
1235                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predQMV.y;
1236            }
1237            else {
1238          pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;          pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1239          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1240            }
1241    
1242          pMB->mvs[block] = *(Data->currentMV);          pMB->mvs[block] = *(Data->currentMV);
1243          pMB->sad8[block] =  4 * (*Data->iMinSAD);          pMB->qmvs[block] = *(Data->currentQMV);
1244    
1245            pMB->sad8[block] =  4 * (*Data->iMinSAD);
1246  }  }
1247    
1248  /* B-frames code starts here */  /* B-frames code starts here */
# Line 947  Line 1303 
1303                          const IMAGE * const pCur,                          const IMAGE * const pCur,
1304                          const int x, const int y,                          const int x, const int y,
1305                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
1306                          const uint32_t iFcode,                          const uint32_t iFcode,
1307                          const MBParam * const pParam,                          const MBParam * const pParam,
1308                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
1309                          const VECTOR * const predMV,                          const VECTOR * const predMV,
1310                          int32_t * const best_sad,                          int32_t * const best_sad,
1311                          const int32_t mode_current)                          const int32_t mode_current,
1312                            SearchData * const Data)
1313  {  {
1314    
1315          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1316    
1317          int i, iDirection, mask;          int i, iDirection, mask;
1318          VECTOR currentMV, pmv[7];          VECTOR pmv[7];
1319          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1320          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
1321          SearchData Data;          Data->iFcode = iFcode;
1322    
1323          Data.iMinSAD = &iMinSAD;          Data->Ref = pRef + (x + y * iEdgedWidth) * 16;
1324          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->RefH = pRefH + (x + y * iEdgedWidth) * 16;
1325          Data.iEdgedWidth = iEdgedWidth;          Data->RefV = pRefV + (x + y * iEdgedWidth) * 16;
1326          Data.currentMV = &currentMV;          Data->RefHV = pRefHV + (x + y * iEdgedWidth) * 16;
         Data.iMinSAD = &iMinSAD;  
         Data.Ref = pRef + (x + y * iEdgedWidth) * 16;  
         Data.RefH = pRefH + (x + y * iEdgedWidth) * 16;  
         Data.RefV = pRefV + (x + y * iEdgedWidth) * 16;  
         Data.RefHV = pRefHV + (x + y * iEdgedWidth) * 16;  
1327    
1328          Data.iQuant = iQuant;          Data->predMV = *predMV;
         Data.iFcode = iFcode;  
         Data.predMV = *predMV;  
   
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,  
                                 pParam->width, pParam->height, iFcode);  
   
         if (!(MotionFlags & PMV_HALFPEL16)) {  
                 Data.min_dx = EVEN(Data.min_dx);  
                 Data.max_dx = EVEN(Data.max_dx);  
                 Data.min_dy = EVEN(Data.min_dy);  
                 Data.max_dy = EVEN(Data.max_dy); } // no-halpel and b-frames. do we need it?  
1329    
1330            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1331                                    pParam->width, pParam->height, iFcode, pParam->m_quarterpel);
1332    
1333          pmv[0] = Data.predMV;          pmv[0] = Data->predMV;
1334          PreparePredictionsBF(pmv, x, y, pParam->mb_width,          PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
                                         pMB, mode_current);  
1335    
1336          currentMV.x = currentMV.y = 0;          Data->currentMV->x = Data->currentMV->y = 0;
1337    
1338          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1339    
1340  // main loop. checking all predictions  // main loop. checking all predictions
1341          for (i = 0; i < 8; i++) {          for (i = 0; i < 8; i++) {
1342                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1343                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1344          }          }
1345    
1346          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1008  Line 1349 
1349                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1350                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1351    
1352          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1353    
1354          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          HalfpelRefine(Data);
1355    
1356  // three bits are needed to code backward mode. four for forward  // three bits are needed to code backward mode. four for forward
1357  // we treat the bits just like they were vector's  // we treat the bits just like they were vector's
1358          if (mode_current == MODE_FORWARD) iMinSAD +=  4 * lambda_vec16[iQuant];          if (mode_current == MODE_FORWARD) *Data->iMinSAD +=  4 * Data->lambda16 * 2;
1359          else iMinSAD +=  3 * lambda_vec16[iQuant];          else *Data->iMinSAD +=  3 * Data->lambda16 * 2;
   
1360    
1361          if (iMinSAD < *best_sad) {          if (*Data->iMinSAD < *best_sad) {
1362                  *best_sad = iMinSAD;                  *best_sad = *Data->iMinSAD;
1363                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1364                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1365                  pMB->pmvs[0].y = currentMV.y - predMV->y;                  pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1366                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = *(Data->currentMV+2) = *Data->currentMV;
1367                  else pMB->b_mvs[0] = currentMV;                  else pMB->b_mvs[0] = *(Data->currentMV+1) = *Data->currentMV; //we store currmv for interpolate search
1368          }          }
1369    
1370  }  }
# Line 1041  Line 1381 
1381                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1382                                  const int x, const int y,                                  const int x, const int y,
1383                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1384                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1385                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1386                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1387                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1388                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1389                                    SearchData * const Data)
1390    
1391  {  {
1392          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
         int32_t iMinSAD = 266*4096, skip_sad;  
1393          int k;          int k;
1394          VECTOR currentMV;  
1395          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
         SearchData Data;  
1396    
1397          Data.iMinSAD = &iMinSAD;          *Data->iMinSAD = 256*4096;
1398          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;  
1399    
1400          Data.Ref= f_Ref->y + (x + iEdgedWidth*y) * 16;          Data->Ref = f_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1401          Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;          Data->RefH = f_RefH + (x + Data->iEdgedWidth*y) * 16;
1402          Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;          Data->RefV = f_RefV + (x + Data->iEdgedWidth*y) * 16;
1403          Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = f_RefHV + (x + Data->iEdgedWidth*y) * 16;
1404          Data.bRef = b_Ref->y + (x + iEdgedWidth*y) * 16;          Data->bRef = b_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1405          Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;          Data->bRefH = b_RefH + (x + Data->iEdgedWidth*y) * 16;
1406          Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;          Data->bRefV = b_RefV + (x + Data->iEdgedWidth*y) * 16;
1407          Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;          Data->bRefHV = b_RefHV + (x + Data->iEdgedWidth*y) * 16;
1408  /*  
1409  //What we do here is a complicated version of CheckCandidateDirect(0,0);          Data->max_dx = 2 * pParam->width - 2 * (x) * 16;
1410  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;
1411            Data->min_dx = -(2 * 16 + 2 * (x) * 16);
1412  */          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);  
1413    
1414          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1415                  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);
1416                  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;
1417                  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);
1418                  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;
1419    
1420                  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 )
1421                          || ( 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 )) {  
1422    
1423                          *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
1424                          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 1428 
1428                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1429                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1430                          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];
1431                          Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1432                          Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1433                          break;                          break;
1434                  }                  }
1435          }          }
# Line 1110  Line 1438 
1438                  CheckCandidate = CheckCandidateDirect;                  CheckCandidate = CheckCandidateDirect;
1439          else CheckCandidate = CheckCandidateDirectno4v;          else CheckCandidate = CheckCandidateDirectno4v;
1440    
1441          (*CheckCandidate)(0, 0, 255, &k, &Data);          (*CheckCandidate)(0, 0, 255, &k, Data);
1442    
1443  // skip decision  // skip decision
1444          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) {
1445                  //checking chroma. everything copied from MC                  //possible skip - checking chroma. everything copied from MC
1446                  //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
1447                  int sum, dx, dy, b_dx, b_dy;                  int sum, dx, dy, b_dx, b_dy;
1448    
# Line 1130  Line 1458 
1458                  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;
1459                  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));
1460    
1461                  sum = sad8bi(pCur->u + 8*x + 8*y*(iEdgedWidth/2),                  sum = sad8bi(pCur->u + 8*x + 8*y*(Data->iEdgedWidth/2),
1462                                          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,
1463                                          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,
1464                                          iEdgedWidth/2);                                          Data->iEdgedWidth/2);
1465                  sum += sad8bi(pCur->v + 8*x + 8*y*(iEdgedWidth/2),                  sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1466                                          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,
1467                                          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,
1468                                          iEdgedWidth/2);                                          Data->iEdgedWidth/2);
1469    
1470                  if ((uint32_t) sum < MAX_CHROMA_SAD_FOR_SKIP * Data.iQuant) {                  if (sum < MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) {
1471                          pMB->mode = MODE_DIRECT_NONE_MV;                          pMB->mode = MODE_DIRECT_NONE_MV;
1472                          return iMinSAD;                          return *Data->iMinSAD;
1473                  }                  }
1474          }          }
1475    
1476          skip_sad = iMinSAD;          skip_sad = *Data->iMinSAD;
1477    
1478  //  DIRECT MODE DELTA VECTOR SEARCH.  //  DIRECT MODE DELTA VECTOR SEARCH.
1479  //      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 1482 
1482                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1483                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1484    
1485          (*MainSearchPtr)(0, 0, &Data, 255);          (*MainSearchPtr)(0, 0, Data, 255);
1486    
1487          HalfpelRefine(&Data);          HalfpelRefine(Data);
1488    
1489          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
1490          *best_sad = iMinSAD;          *best_sad = *Data->iMinSAD;
1491    
1492          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1493                  pMB->mode = MODE_DIRECT;                  pMB->mode = MODE_DIRECT;
1494          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1495    
1496          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1497    
1498          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1499                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1500                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = ((Data->currentMV->x == 0)
1501                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1502                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          : pMB->mvs[k].x - Data->referencemv[k].x);
1503                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1504                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1505                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1506                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1507                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1508                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1509                          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];
1510                          break;                          break;
1511                  }                  }
1512          }          }
1513          return 0;//skip_sad;          return skip_sad;
1514  }  }
1515    
1516    
1517  static __inline void  static __inline void
1518  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const uint8_t * const f_Ref,
1519                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
# Line 1199  Line 1528 
1528                                  const uint32_t fcode,                                  const uint32_t fcode,
1529                                  const uint32_t bcode,                                  const uint32_t bcode,
1530                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1531                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1532                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1533                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1534                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1535                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1536                                    SearchData * const fData)
1537    
1538  {  {
 /* 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". */  
1539    
1540          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1541    
1542          int iDirection, i, j;          int iDirection, i, j;
1543          int32_t iMinSAD = 256*4096;          SearchData bData;
         VECTOR currentMV[3];  
         SearchData fData, bData;  
   
         fData.iMinSAD = bData.iMinSAD = &iMinSAD;  
1544    
1545          fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          *(bData.iMinSAD = fData->iMinSAD) = 4096*256;
1546          fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;          bData.Cur = fData->Cur;
1547          fData.currentMV = currentMV; bData.currentMV = currentMV + 1;          fData->iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;
1548          fData.iQuant = bData.iQuant = iQuant;          bData.currentMV = fData->currentMV + 1;
1549          fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;          bData.lambda16 = fData->lambda16;
1550            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1551          bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  
1552          bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;          bData.bRef = fData->Ref = f_Ref + (x + y * iEdgedWidth) * 16;
1553          bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;          bData.bRefH = fData->RefH = f_RefH + (x + y * iEdgedWidth) * 16;
1554          bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;          bData.bRefV = fData->RefV = f_RefV + (x + y * iEdgedWidth) * 16;
1555          bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;          bData.bRefHV = fData->RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;
1556          bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;          bData.Ref = fData->bRef = b_Ref + (x + y * iEdgedWidth) * 16;
1557          bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;          bData.RefH = fData->bRefH = b_RefH + (x + y * iEdgedWidth) * 16;
1558          bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;          bData.RefV = fData->bRefV = b_RefV + (x + y * iEdgedWidth) * 16;
1559            bData.RefHV = fData->bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;
1560          bData.bpredMV = fData.predMV = *f_predMV;  
1561          fData.bpredMV = bData.predMV = *b_predMV;          bData.bpredMV = fData->predMV = *f_predMV;
1562            fData->bpredMV = bData.predMV = *b_predMV;
1563          currentMV[0] = pMB->mvs[0];  
1564          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
1565          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);
1566          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);
1567    
1568          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;
1569          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;
1570          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;
1571          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;
1572    
1573          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;
1574          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;
1575          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;
1576          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;
1577    
1578          CheckCandidateInt(currentMV[0].x, currentMV[0].y, 255, &iDirection, &fData);          CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
1579    
1580  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)
1581    
1582          do {          do {
1583                  iDirection = 255;                  iDirection = 255;
1584                  // forward MV moves                  // forward MV moves
1585                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
1586    
1587                  CheckCandidateInt(i + 1, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1588                  CheckCandidateInt(i, j + 1, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1589                  CheckCandidateInt(i - 1, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1590                  CheckCandidateInt(i, j - 1, 0, &iDirection, &fData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
1591    
1592                  // backward MV moves                  // backward MV moves
1593                  i = currentMV[1].x; j = currentMV[1].y;                  i = fData->currentMV[1].x; j = fData->currentMV[1].y;
1594                  currentMV[2] = currentMV[0];                  fData->currentMV[2] = fData->currentMV[0];
1595    
1596                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1597                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
# Line 1280  Line 1601 
1601          } while (!(iDirection));          } while (!(iDirection));
1602    
1603  // 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
1604          iMinSAD +=  2 * lambda_vec16[iQuant];          *fData->iMinSAD +=  2 * fData->lambda16 * 2;
1605          if (iMinSAD < *best_sad) {          if (*fData->iMinSAD < *best_sad) {
1606                  *best_sad = iMinSAD;                  *best_sad = *fData->iMinSAD;
1607                  pMB->mvs[0] = currentMV[0];                  pMB->mvs[0] = fData->currentMV[0];
1608                  pMB->b_mvs[0] = currentMV[1];                  pMB->b_mvs[0] = fData->currentMV[1];
1609                  pMB->mode = MODE_INTERPOLATE;                  pMB->mode = MODE_INTERPOLATE;
1610    
1611                  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 1615 
1615          }          }
1616  }  }
1617    
1618    
1619  void  void
1620  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
1621                                           FRAMEINFO * const frame,                                           FRAMEINFO * const frame,
# Line 1322  Line 1644 
1644          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1645          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
1646    
1647    // some pre-inintialized data for the rest of the search
1648    
1649            SearchData Data;
1650            int32_t iMinSAD;
1651            VECTOR currentMV[3];
1652            Data.iEdgedWidth = pParam->edged_width;
1653            Data.currentMV = currentMV;
1654            Data.iMinSAD = &iMinSAD;
1655            Data.lambda16 = lambda_vec16[frame->quant];
1656    
1657          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
1658    
1659          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
# Line 1338  Line 1670 
1670                                  continue;                                  continue;
1671                          }                          }
1672    
1673                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
1674                            pMB->quant = frame->quant;
1675  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
1676          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
1677    
# Line 1346  Line 1680 
1680                                                                          &frame->image,                                                                          &frame->image,
1681                                                                          i, j,                                                                          i, j,
1682                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
1683                                                                          TRB, TRD,                                                                          TRB, TRD,
1684                                                                          pParam,                                                                          pParam,
1685                                                                          pMB, b_mb,                                                                          pMB, b_mb,
1686                                                                          &best_sad);                                                                          &best_sad,
1687                                                                            &Data);
1688    
1689                          if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                          if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1690    
# Line 1361  Line 1695 
1695                          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,
1696                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1697                                                  frame->motion_flags,                                                  frame->motion_flags,
1698                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
1699                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
1700                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
1701    
1702                          // backward search                          // backward search
1703                          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,
1704                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1705                                                  frame->motion_flags,                                                  frame->motion_flags,
1706                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
1707                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
1708                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
1709    
1710                          // 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
1711    
# Line 1381  Line 1715 
1715                                                  i, j,                                                  i, j,
1716                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
1717                                                  frame->motion_flags,                                                  frame->motion_flags,
1718                                                  frame->quant, pParam,                                                  pParam,
1719                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
1720                                                  pMB, &best_sad);                                                  pMB, &best_sad,
1721                                                    &Data);
1722    
1723                          switch (pMB->mode) {                          switch (pMB->mode) {
1724                                  case MODE_FORWARD:                                  case MODE_FORWARD:
# Line 1416  Line 1751 
1751    
1752  /* Hinted ME starts here */  /* Hinted ME starts here */
1753    
1754  static __inline void  static void
1755  Search8hinted(  const SearchData * const OldData,  Search8hinted(  const SearchData * const OldData,
1756                                  const int x, const int y,                                  const int x, const int y,
1757                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1758                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1759                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1760                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1761                                  const int block)                          const int block,
1762                            SearchData * const Data)
1763  {  {
1764          SearchData Data;          int32_t temp_sad;
1765          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1766            Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1767            Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1768            Data->iMinSAD = OldData->iMinSAD + 1 + block;
1769            Data->currentMV = OldData->currentMV + 1 + block;
1770            Data->currentQMV = OldData->currentQMV + 1 + block;
1771    
1772          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          if(pParam->m_quarterpel) {
1773          Data.iMinSAD = OldData->iMinSAD + 1 + block;                  //it is qpel. substract d_mv_bits[qpel] from 0, add d_mv_bits[hpel] everywhere
1774          Data.currentMV = OldData->currentMV+1+block;                  if (block == 0)
1775          Data.iFcode = OldData->iFcode;                          *(Data->iMinSAD) -= Data->lambda8 *
1776          Data.iQuant = OldData->iQuant;                                                                          d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1777                                                                                                    Data->currentQMV->y - Data->predQMV.y,
1778          Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));                                                                                                  Data->iFcode);
         Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));  
         Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));  
         Data.RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));  
         Data.iEdgedWidth = pParam->edged_width;  
         Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));  
1779    
1780          CheckCandidate = CheckCandidate8;                  *(Data->iMinSAD) += Data->lambda8 *
1781                                                                            d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1782                                                                                                    Data->currentMV->y - Data->predMV.y,
1783                                                                                                    Data->iFcode);
1784            } else //it is not qpel. add d_mv_bits[hpel] everywhere but not in 0 (it's already there)
1785                    if (block != 0) *(Data->iMinSAD) += Data->lambda8 *
1786                                                                            d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1787                                                                                                    Data->currentMV->y - Data->predMV.y,
1788                                                                                                    Data->iFcode);
1789    
         if (block != 0)  
                 *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *  
                                                                 d_mv_bits(      Data.currentMV->x - Data.predMV.x,  
                                                                                         Data.currentMV->y - Data.predMV.y,  
                                                                                         Data.iFcode);  
1790    
1791            Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));
1792            Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));
1793            Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1794            Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1795            Data->RefQ = OldData->RefQ;
1796    
1797            Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
1798    
1799          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,
1800                                  pParam->width, pParam->height, OldData->iFcode);                                  pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1801    
1802          if (pMB->mode == MODE_INTER4V) {          CheckCandidate = CheckCandidate8;
1803                  int dummy;  
1804                  CheckCandidate8(pMB->mvs[block].x, pMB->mvs[block].y, 0, &dummy, &Data); }          temp_sad = *(Data->iMinSAD); // store current MinSAD
1805    
1806          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1807                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1808                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1809    
1810          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1811    
1812            if(*(Data->iMinSAD) < temp_sad) {
1813                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1814                    Data->currentQMV->y = 2 * Data->currentMV->y;
1815            }
1816    
1817            if (MotionFlags & PMV_HALFPELREFINE8) {
1818                    temp_sad = *(Data->iMinSAD); // store current MinSAD
1819    
1820                    HalfpelRefine(Data); // perform halfpel refine of current best vector
1821    
1822                    if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1823                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1824                            Data->currentQMV->y = 2 * Data->currentMV->y;
1825                    }
1826            }
1827    
1828            if(pParam->m_quarterpel) {
1829                    if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1830                            (MotionFlags & PMV_QUARTERPELREFINE8)) {
1831    
1832                            CheckCandidate = CheckCandidate8_qpel;
1833                            Data->iMinSAD[0] -= Data->lambda8 *
1834                                    d_mv_bits(Data->predMV.x - Data->currentMV[0].x, Data->predMV.y - Data->currentMV[0].y, Data->iFcode);
1835    
1836                            Data->iMinSAD[0] += Data->lambda8 *
1837                                    d_mv_bits(Data->predQMV.x - Data->currentQMV[0].x, Data->predQMV.y - Data->currentQMV[0].y, Data->iFcode);
1838    
1839                                    QuarterpelRefine(Data);
1840                    }
1841            pMB->pmvs[block].x = Data->currentQMV->x - Data->predQMV.x;
1842            pMB->pmvs[block].y = Data->currentQMV->y - Data->predQMV.y;
1843            } else {
1844                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1845                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1846            }
1847    
1848          if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);          pMB->mvs[block] = *(Data->currentMV);
1849            pMB->qmvs[block] = *(Data->currentQMV);
1850    
1851          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;          pMB->sad8[block] =  4 * (*Data->iMinSAD);
         pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;  
         pMB->mvs[block] = *(Data.currentMV);  
         pMB->sad8[block] =  4 * (*(Data.iMinSAD));  
1852  }  }
1853    
1854    
# Line 1482  Line 1862 
1862                                  const int y,                                  const int y,
1863                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1864                                  const uint32_t iQuant,                                  const uint32_t iQuant,
                                 const uint32_t iFcode,  
1865                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1866                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1867                                  int inter4v,                                  int inter4v,
1868                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
1869                                    SearchData * const Data)
1870  {  {
1871    
1872          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1873    
1874          int i;          int i, t;
         VECTOR currentMV[5];  
         int32_t iMinSAD[5];  
         int32_t temp[5];  
1875          MainSearchFunc * MainSearchPtr;          MainSearchFunc * MainSearchPtr;
         SearchData Data;  
1876    
1877          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1878          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,
1879                                  pParam->width, pParam->height, iFcode);                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
1880    
1881          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->Cur = pCur->y + (x + y * iEdgedWidth) * 16;
1882          Data.iEdgedWidth = iEdgedWidth;          Data->Ref = pRef + (x + iEdgedWidth*y)*16;
1883          Data.currentMV = currentMV;          Data->RefH = pRefH + (x + iEdgedWidth*y) * 16;
1884          Data.iMinSAD = iMinSAD;          Data->RefV = pRefV + (x + iEdgedWidth*y) * 16;
1885          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data->RefHV = pRefHV + (x + iEdgedWidth*y) * 16;
1886          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->lambda16 = lambda_vec16[iQuant];
         Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;  
         Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;  
         Data.temp = temp;  
         Data.iQuant = iQuant;  
         Data.iFcode = iFcode;  
1887    
1888          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
1889                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
1890                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
1891                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
1892                  Data.max_dy = EVEN(Data.max_dy);                  Data->max_dy = EVEN(Data->max_dy);
1893          }          }
1894    
1895          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;          for(i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
1896    
1897          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
1898    
# Line 1532  Line 1903 
1903    
1904          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);
1905          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);
1906          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
1907          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;
1908          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;
1909          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;
1910    
1911          CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);          (*CheckCandidate)(pMB->mvs[0].x, pMB->mvs[0].y, 0, &t, Data);
1912    
1913          if (pMB->mode == MODE_INTER4V)          if (pMB->mode == MODE_INTER4V)
1914                  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
1915                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);
1916                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);
1917                          if (!(make_mask(pMB->mvs, i)))                          if (!(make_mask(pMB->mvs, i)))
1918                                  CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);                                  (*CheckCandidate)(pMB->mvs[i].x, pMB->mvs[i].y, 0, &t, Data);
1919                  }                  }
1920    
1921          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1553  Line 1924 
1924                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1925                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1926    
1927          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1928    
1929            if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1930    
1931            for(i = 0; i < 5; i++) {
1932                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1933                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1934            }
1935    
1936          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1937    
1938          if (inter4v)          if (inter4v)
1939                  for(i = 0; i < 4; i++)                          CheckCandidate = CheckCandidate16_qpel;
1940                          Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                  else
1941                            CheckCandidate = CheckCandidate16no4v_qpel;
1942    
1943                    QuarterpelRefine(Data);
1944            }
1945    
1946    
1947            if (inter4v) {
1948                    SearchData Data8;
1949                    Data8.iFcode = Data->iFcode;
1950                    Data8.lambda8 = lambda_vec8[pMB->quant];
1951                    Data8.iEdgedWidth = Data->iEdgedWidth;
1952                    Search8hinted(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1953                    Search8hinted(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1954                    Search8hinted(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1955                    Search8hinted(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1956            }
1957    
1958          if (!(inter4v) ||          if (!(inter4v) ||
1959                  (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] +
1960                                                            Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1961  // INTER MODE  // INTER MODE
1962    
1963                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1964                  pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1965                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1966    
1967                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1968                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1969    
1970                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1971                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1972          } else {          } else {
1973  // INTER4V MODE; all other things are already set in Search8hinted  // INTER4V MODE; all other things are already set in Search8hinted
1974                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1975                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3]
1976                                                    + Data->iMinSAD[4] + IMV16X16 * iQuant;
1977          }          }
1978    
1979  }  }
# Line 1595  Line 1991 
1991          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
1992    
1993          uint32_t x, y;          uint32_t x, y;
1994            uint8_t * qimage;
1995            int32_t temp[5], quant = current->quant;
1996            int32_t iMinSAD[5];
1997            VECTOR currentMV[5];
1998            SearchData Data;
1999            Data.iEdgedWidth = pParam->edged_width;
2000            Data.currentMV = currentMV;
2001            Data.iMinSAD = iMinSAD;
2002            Data.temp = temp;
2003            Data.iFcode = current->fcode;
2004            Data.rounding = pParam->m_rounding_type;
2005    
2006            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
2007                    return; // allocate some mem for qpel interpolated blocks
2008                                      // somehow this is dirty since I think we shouldn't use malloc outside
2009                                      // encoder_create() - so please fix me!
2010    
2011            Data.RefQ = qimage;
2012    
2013          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
2014    
# Line 1606  Line 2020 
2020  //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
2021                          if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;                          if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;
2022    
2023    
2024                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
2025                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
2026                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant; }
2027                            else
2028                                    if (pMB->dquant != NO_CHANGE) {
2029                                            quant += DQtab[pMB->dquant];
2030                                            if (quant > 31) quant = 31;
2031                                            else if (quant < 1) quant = 1;
2032                                            pMB->quant = quant;
2033                                    }
2034    
2035                          SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
2036                                                          y, current->motion_flags, pMB->quant,                                                          y, current->motion_flags, pMB->quant,
2037                                                          current->fcode, pParam, pMBs,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
2038                                                          current->global_flags & XVID_INTER4V, pMB);                                                          &Data);
2039    
2040                  }                  }
2041          }          }
2042            free(qimage);
2043  }  }
2044    
2045  static __inline int  static __inline int
# Line 1624  Line 2047 
2047                                  const uint8_t * const pCur,                                  const uint8_t * const pCur,
2048                                  const int x,                                  const int x,
2049                                  const int y,                                  const int y,
                                 const uint32_t iFcode,  
2050                                  const MBParam * const pParam,                                  const MBParam * const pParam,
2051                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
2052                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
2053                                    SearchData * const Data)
2054  {  {
2055    
         const int32_t iEdgedWidth = pParam->edged_width;  
2056          int i, mask;          int i, mask;
2057          VECTOR currentMV, pmv[3];          VECTOR pmv[3];
         int32_t iMinSAD = MV_MAX_ERROR;  
         SearchData Data;  
2058    
2059          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          *(Data->iMinSAD) = MV_MAX_ERROR;
2060          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);
2061                                  pParam->width, pParam->height, iFcode);          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2062                                    pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
2063    
2064          Data.Cur = pCur + (x + y * iEdgedWidth) * 16;          Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
2065          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;  
2066    
2067          CheckCandidate = CheckCandidate16no4vI;          CheckCandidate = CheckCandidate16no4vI;
2068    
2069          pmv[1].x = EVEN(pMB->mvs[0].x);          pmv[1].x = EVEN(pMB->mvs[0].x);
2070          pmv[1].y = EVEN(pMB->mvs[0].y);          pmv[1].y = EVEN(pMB->mvs[0].y);
2071          pmv[0].x = EVEN(Data.predMV.x);          pmv[0].x = EVEN(Data->predMV.x);
2072          pmv[0].y = EVEN(Data.predMV.y);          pmv[0].y = EVEN(Data->predMV.y);
2073          pmv[2].x = pmv[2].y = 0;          pmv[2].x = pmv[2].y = 0;
2074    
2075          CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, &Data);          CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, Data);
2076          if (!(mask = make_mask(pmv, 1)))          if (!(mask = make_mask(pmv, 1)))
2077                  CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, &Data);                  CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, Data);
2078          if (!(mask = make_mask(pmv, 2)))          if (!(mask = make_mask(pmv, 2)))
2079                  CheckCandidate16no4vI(0, 0, mask, &i, &Data);                  CheckCandidate16no4vI(0, 0, mask, &i, Data);
2080    
2081          DiamondSearch(currentMV.x, currentMV.y, &Data, i);          DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, mask);
2082    
2083          pMB->mvs[0] = pMB->mvs[1]          pMB->mvs[0] = pMB->mvs[1]
2084                          = pMB->mvs[2] = pMB->mvs[3] = currentMV; // all, for future get_pmv()                          = pMB->mvs[2] = pMB->mvs[3] = *Data->currentMV; // all, for future get_pmv()
2085    
2086          return iMinSAD;          return *(Data->iMinSAD);
2087  }  }
2088    
2089  #define INTRA_THRESH    1350  #define INTRA_THRESH    1350
# Line 1683  Line 2099 
2099          uint32_t x, y, intra = 0;          uint32_t x, y, intra = 0;
2100          int sSAD = 0;          int sSAD = 0;
2101    
2102            VECTOR currentMV;
2103            int32_t iMinSAD;
2104            SearchData Data;
2105            Data.iEdgedWidth = pParam->edged_width;
2106            Data.currentMV = &currentMV;
2107            Data.iMinSAD = &iMinSAD;
2108            Data.iFcode = iFcode;
2109    
2110          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
2111    
2112          for (y = 0; y < pParam->mb_height-1; y++) {          for (y = 1; y < pParam->mb_height-1; y++) {
2113                  for (x = 0; x < pParam->mb_width; x++) {                  for (x = 1; x < pParam->mb_width-1; x++) {
2114                          int sad, dev;                          int sad, dev;
   
2115                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2116    
2117                          sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,                          sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
2118                                                                  iFcode, pParam, pMBs, pMB);                                                                  pParam, pMBs, pMB, &Data);
2119    
                         if ( x != 0 && y != 0 && x != pParam->mb_width-1 ) { //no edge macroblocks, they just don't work  
2120                                  if (sad > INTRA_THRESH) {                                  if (sad > INTRA_THRESH) {
2121                                          dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                          dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
2122                                                                    pParam->edged_width);                                                                    pParam->edged_width);
# Line 1703  Line 2125 
2125                                  }                                  }
2126                                  sSAD += sad;                                  sSAD += sad;
2127                          }                          }
   
                 }  
2128          }          }
2129          sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);          sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2130          if (sSAD > INTER_THRESH ) return 1; //P frame          if (sSAD > INTER_THRESH ) return 1; //P frame
# Line 1712  Line 2132 
2132          return 0; // B frame          return 0; // B frame
2133    
2134  }  }
2135    
2136    int
2137    FindFcode(      const MBParam * const pParam,
2138                            const FRAMEINFO * const current)
2139    {
2140            uint32_t x, y;
2141            int max = 0, min = 0, i;
2142    
2143            for (y = 0; y < pParam->mb_height; y++) {
2144                    for (x = 0; x < pParam->mb_width; x++) {
2145    
2146                            MACROBLOCK *pMB = &current->mbs[x + y * pParam->mb_width];
2147                            for(i = 0; i < (pMB->mode == MODE_INTER4V ? 4:1); i++) {
2148                                    if (pMB->mvs[i].x > max) max = pMB->mvs[i].x;
2149                                    if (pMB->mvs[i].y > max) max = pMB->mvs[i].y;
2150    
2151                                    if (pMB->mvs[i].x < min) min = pMB->mvs[i].x;
2152                                    if (pMB->mvs[i].y < min) min = pMB->mvs[i].y;
2153                            }
2154                    }
2155            }
2156    
2157            min = -min;
2158            max += 1;
2159            if (min > max) max = min;
2160    
2161            for (i = 1; (max > 32 << (i - 1)); i++);
2162            return i;
2163    }

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

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