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

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

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

revision 530, Mon Sep 23 20:36:02 2002 UTC revision 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"
44    #include "../utils/emms.h"
45    
46  #define INITIAL_SKIP_THRESH     (10)  #define INITIAL_SKIP_THRESH     (10)
47  #define FINAL_SKIP_THRESH       (50)  #define FINAL_SKIP_THRESH       (50)
48  #define MAX_SAD00_FOR_SKIP      (20)  #define MAX_SAD00_FOR_SKIP      (20)
49  #define MAX_CHROMA_SAD_FOR_SKIP (18)  #define MAX_CHROMA_SAD_FOR_SKIP (22)
50  #define SKIP_THRESH_B (10)  #define SKIP_THRESH_B (25)
51    
52  #define CHECK_CANDIDATE(X,Y,D) { \  #define CHECK_CANDIDATE(X,Y,D) { \
53  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }
54    
55  #define iDiamondSize 2  #define GET_REFERENCE(X, Y, REF) { \
56            switch ( (((X)&1)<<1) + ((Y)&1) ) \
57            { \
58                    case 0 : REF = (uint8_t *)data->Ref + (X)/2 + ((Y)/2)*(data->iEdgedWidth); break; \
59                    case 1 : REF = (uint8_t *)data->RefV + (X)/2 + (((Y)-1)/2)*(data->iEdgedWidth); break; \
60                    case 2 : REF = (uint8_t *)data->RefH + ((X)-1)/2 + ((Y)/2)*(data->iEdgedWidth); break; \
61                    default : REF = (uint8_t *)data->RefHV + ((X)-1)/2 + (((Y)-1)/2)*(data->iEdgedWidth); break; \
62            } \
63    }
64    
65  //FILE * debug;  #define iDiamondSize 2
66    
67  static __inline int  static __inline int
68  d_mv_bits(int x, int y, const uint32_t iFcode)  d_mv_bits(int x, int y, const uint32_t iFcode)
# Line 79  Line 89 
89          return xb + yb;          return xb + yb;
90  }  }
91    
92  /* CHACK_CANDIATE FUNCTIONS START */  
93    /* CHECK_CANDIATE FUNCTIONS START */
94    
95  static void  static void
96  CheckCandidate16(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidate16(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
97  {  {
         int32_t * const sad = data->temp;  
 //      static int32_t sad[5];  
98          int t;          int t;
99          const uint8_t * Reference;          const uint8_t * Reference;
100    
# Line 99  Line 108 
108                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;
109          }          }
110    
111          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, sad+1);          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
112    
113          t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
114          data->temp[0] += lambda_vec16[data->iQuant] * t;          data->temp[0] += data->lambda16 * t;
115          data->temp[1] += lambda_vec8[data->iQuant] * t;          data->temp[1] += data->lambda8 * t;
116    
117          if (data->temp[0] < data->iMinSAD[0]) {          if (data->temp[0] < data->iMinSAD[0]) {
118                  data->iMinSAD[0] = data->temp[0];                  data->iMinSAD[0] = data->temp[0];
# Line 138  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);
152          sad += sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);  
153            if (sad < *(data->iMinSAD)) {
154                    *(data->iMinSAD) = sad;
155                    data->currentMV[0].x = x; data->currentMV[0].y = y;
156                    *dir = Direction; }
157    }
158    
159    static void
160    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;
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)
254                    || ( y > data->max_dy) || (y < data->min_dy)) return;
255    
256            switch( ((x&1)<<1) + (y&1) )
257            {
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            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);
317    
318          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
319                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 148  Line 321 
321                  *dir = Direction; }                  *dir = Direction; }
322  }  }
323    
324    
325  static void  static void
326  CheckCandidateInt(const int xf, const int yf, const int Direction, int * const dir, const SearchData * const data)  CheckCandidateInt(const int xf, const int yf, const int Direction, int * const dir, const SearchData * const data)
327  {  {
# Line 173  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 196  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 249  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 308  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 316  Line 490 
490                  *dir = Direction; }                  *dir = Direction; }
491  }  }
492    
493  /* CHACK_CANDIATE FUNCTIONS END */  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 */
552    
553  /* MAINSEARCH FUNCTIONS START */  /* MAINSEARCH FUNCTIONS START */
554    
# Line 484  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 497  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 508  Line 762 
762  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)
763  {  {
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 = pMB->mv16.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 = pMB->mv16.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 530  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
795            int32_t temp[5];
796            VECTOR currentMV[5];
797            VECTOR currentQMV[5];
798            int32_t iMinSAD[5];
799            SearchData Data;
800            Data.iEdgedWidth = pParam->edged_width;
801            Data.currentMV = currentMV;
802            Data.currentQMV = currentQMV;
803            Data.iMinSAD = iMinSAD;
804            Data.temp = temp;
805            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 545  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                                                  current->fcode, 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 582  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->mv16 = 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 601  Line 891 
891  static __inline int  static __inline int
892  make_mask(const VECTOR * const pmv, const int i)  make_mask(const VECTOR * const pmv, const int i)
893  {  {
894          int mask = 0xFF, j;          int mask = 255, j;
895          for (j = 0; j < i; j++) {          for (j = 0; j < i; j++) {
896                  if (MVequal(pmv[i], pmv[j])) return 0; // same vector has been checked already                  if (MVequal(pmv[i], pmv[j])) return 0; // same vector has been checked already
897                  if (pmv[i].x == pmv[j].x) {                  if (pmv[i].x == pmv[j].x) {
# Line 625  Line 915 
915    
916          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour
917                  pmv[5].x = EVEN(pmv[3].x);                  pmv[5].x = EVEN(pmv[3].x);
918                  pmv[5].y = EVEN(pmv[3].y); }                  pmv[5].y = EVEN(pmv[3].y);
919          else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
920    
921          if (x != 0) { pmv[3].x = EVEN(pmv[1].x); pmv[3].y = EVEN(pmv[1].y); }// pmv[3] is left neighbour          if (x != 0) { pmv[3].x = EVEN(pmv[1].x); pmv[3].y = EVEN(pmv[1].y); }// pmv[3] is left neighbour
922          else pmv[3].x = pmv[3].y = 0;          else pmv[3].x = pmv[3].y = 0;
# Line 644  Line 934 
934    
935          if ((x != iWcount-1) && (y != iHcount-1)) {          if ((x != iWcount-1) && (y != iHcount-1)) {
936                  pmv[6].x = EVEN((prevMB+1+iWcount)->mvs[0].x); //[6] right-down neighbour in last frame                  pmv[6].x = EVEN((prevMB+1+iWcount)->mvs[0].x); //[6] right-down neighbour in last frame
937                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y); }                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
938          else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
939  }  }
940    
941  static void  static void
# Line 653  Line 943 
943                  const uint8_t * const pRefH,                  const uint8_t * const pRefH,
944                  const uint8_t * const pRefV,                  const uint8_t * const pRefV,
945                  const uint8_t * const pRefHV,                  const uint8_t * const pRefHV,
946                    const uint8_t * const pRefQ,
947                  const IMAGE * const pCur,                  const IMAGE * const pCur,
948                  const int x,                  const int x,
949                  const int y,                  const int y,
950                  const uint32_t MotionFlags,                  const uint32_t MotionFlags,
951                  const uint32_t iQuant,                  const uint32_t iQuant,
952                  const uint32_t iFcode,                  SearchData * const Data,
953                  const MBParam * const pParam,                  const MBParam * const pParam,
954                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
955                  const MACROBLOCK * const prevMBs,                  const MACROBLOCK * const prevMBs,
# Line 666  Line 957 
957                  MACROBLOCK * const pMB)                  MACROBLOCK * const pMB)
958  {  {
959    
         const int32_t iEdgedWidth = pParam->edged_width;  
   
960          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
961          int32_t temp[5];          VECTOR pmv[7];
         VECTOR currentMV[5], pmv[7];  
         int32_t psad[4], iMinSAD[5];  
         MainSearchFunc * MainSearchPtr;  
         SearchData Data;  
962    
963          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, psad);  //has to be changed to get_pmv(2)()          Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,  
                                 pParam->width, pParam->height, iFcode);  
   
         Data.predMV = pmv[0];  
         Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
         Data.iEdgedWidth = iEdgedWidth;  
         Data.currentMV = currentMV;  
         Data.iMinSAD = iMinSAD;  
         Data.Ref = pRef + (x + iEdgedWidth*y)*16;  
         Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;  
         Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;  
         Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;  
         Data.temp = temp;  
964    
965          Data.iQuant = iQuant;          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()
966          Data.iFcode = iFcode;          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->m_quarterpel);
968    
969            Data->predMV = pmv[0];
970    
971            Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
972            Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;
973            Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
974            Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
975            Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
976            Data->RefQ = pRefQ;
977    
978            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);
982                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
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); }
   
         for(i = 0;  i < 5; i++) currentMV[i].x = currentMV[i].y = 0;  
   
         i = d_mv_bits(pmv[0].x, pmv[0].y, iFcode);  
   
         iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;  
         iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;  
         iMinSAD[2] = pMB->sad8[1];  
         iMinSAD[3] = pMB->sad8[2];  
         iMinSAD[4] = pMB->sad8[3];  
985    
986          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
987    
988            if (inter4v) CheckCandidate = CheckCandidate16;
989            else CheckCandidate = CheckCandidate16no4v;
990    
991            for(i = 0;  i < 5; i++)
992                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
993    
994            i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);
995            Data->iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;
996            Data->iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;
997            Data->iMinSAD[2] = pMB->sad8[1];
998            Data->iMinSAD[3] = pMB->sad8[2];
999            Data->iMinSAD[4] = pMB->sad8[3];
1000    
1001          if ((x == 0) && (y == 0)) threshA = 512;          if ((x == 0) && (y == 0)) threshA = 512;
1002          else {          else {
1003                  threshA = psad[0] + 20;                  threshA = Data->temp[0]; // that's when we keep this SAD atm
1004                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
1005                  if (threshA > 1024) threshA = 1024; }                  if (threshA > 1024) threshA = 1024; }
1006    
# Line 723  Line 1010 
1010          if (inter4v) CheckCandidate = CheckCandidate16;          if (inter4v) CheckCandidate = CheckCandidate16;
1011          else CheckCandidate = CheckCandidate16no4v;          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 (iMinSAD[0] < threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1020          }          }
1021    
1022          if ((iMinSAD[0] <= threshA) ||          if ((Data->iMinSAD[0] <= threshA) ||
1023                          (MVequal(currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
1024                          (iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {                          (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {
1025                  inter4v = 0;                  inter4v = 0;
1026                  if (MotionFlags & PMV_QUICKSTOP16) goto PMVfast16_Terminate_without_Refine;          } else {
                 if (MotionFlags & PMV_EARLYSTOP16) {  
                         CheckCandidate = CheckCandidate16no4v; // I sure hope it's faster  
                         goto PMVfast16_Terminate_with_Refine;  
                 }  
         }  
1027    
1028          if (MotionFlags & PMV_USESQUARES16)                  MainSearchFunc * MainSearchPtr;
1029                  MainSearchPtr = SquareSearch;                  if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
1030          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
                 MainSearchPtr = AdvDiamondSearch;  
1031                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1032    
1033          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, iDirection);                  (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1034    
1035  /* extended search, diamond starting in 0,0 and in prediction.  /* extended search, diamond starting in 0,0 and in prediction.
1036          note that this search is/might be done in halfpel positions,          note that this search is/might be done in halfpel positions,
# Line 756  Line 1038 
1038    
1039          if (MotionFlags & PMV_EXTSEARCH16) {          if (MotionFlags & PMV_EXTSEARCH16) {
1040                  int32_t bSAD;                  int32_t bSAD;
1041                  VECTOR startMV = Data.predMV, backupMV = currentMV[0];                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
1042                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?
1043                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);
1044                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1045                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1046    
1047                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, Data);
1048                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1049                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1050                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1051                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1052                  }                  }
1053    
1054                  backupMV = currentMV[0];                          backupMV = Data->currentMV[0];
1055                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;
1056                  else startMV.x = startMV.y = 0;                  else startMV.x = startMV.y = 0;
1057                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1058                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1059    
1060                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, Data);
1061                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1062                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1063                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1064                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1065                            }
1066                  }                  }
1067          }          }
1068    
1069  PMVfast16_Terminate_with_Refine:          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1070    
1071          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          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  PMVfast16_Terminate_without_Refine:          if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1077    
1078          if (inter4v)          if (inter4v)
1079                  for(i = 0; i < 4; i++)                          CheckCandidate = CheckCandidate16_qpel;
1080                          Search8(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                  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) {
1100                    SearchData Data8;
1101                    Data8.iFcode = Data->iFcode;
1102                    Data8.lambda8 = lambda_vec8[iQuant];
1103                    Data8.iEdgedWidth = Data->iEdgedWidth;
1104                    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);
1106                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1107                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1108            }
1109    
1110          if (!(inter4v) ||          if (!(inter4v) ||
1111                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
1112                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1113  // INTER MODE  // INTER MODE
1114                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1115                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1116                          = pMB->mvs[2] = pMB->mvs[3] = 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] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1123    
1124                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1125                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          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;
1130                            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 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1136                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1137          }          }
   
1138  }  }
1139    
1140  static void  static void
# Line 820  Line 1144 
1144                  const MBParam * const pParam,                  const MBParam * const pParam,
1145                  MACROBLOCK * const pMB,                  MACROBLOCK * const pMB,
1146                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
1147                  const int block)                  const int block,
1148                    SearchData * const Data)
1149  {  {
1150          SearchData Data;          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.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1153          Data.iMinSAD = OldData->iMinSAD + 1 + block;          Data->currentMV = OldData->currentMV + 1 + block;
1154          Data.currentMV = OldData->currentMV+1+block;          Data->currentQMV = OldData->currentQMV + 1 + block;
1155          Data.iFcode = OldData->iFcode;  
1156          Data.iQuant = OldData->iQuant;          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)                  if (block == 0)
1159                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *                          *(Data->iMinSAD) -= Data->lambda8 *
1160                                                                  d_mv_bits(      Data.currentMV->x - Data.predMV.x,                                                                          d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1161                                                                                          Data.currentMV->y - Data.predMV.y,                                                                                                  Data->currentQMV->y - Data->predQMV.y,
1162                                                                                          Data.iFcode);                                                                                                  Data->iFcode);
1163    
1164                    *(Data->iMinSAD) += Data->lambda8 *
1165                                                                            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,
1171                                                                                                    Data->currentMV->y - Data->predMV.y,
1172                                                                                                    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;
                 Data.iEdgedWidth = pParam->edged_width;  
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 (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                          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          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;                  if (MotionFlags & PMV_HALFPELREFINE8) {
1207          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;                          int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1208          pMB->mvs[block] = *(Data.currentMV);  
1209          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                          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                                    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;
1239                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1240            }
1241    
1242            pMB->mvs[block] = *(Data->currentMV);
1243            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 896  Line 1270 
1270          pmv[2] = ChoosePred(pMB, mode_curr);          pmv[2] = ChoosePred(pMB, mode_curr);
1271          pmv[2].x = EVEN(pmv[2].x); pmv[2].y = EVEN(pmv[2].y);          pmv[2].x = EVEN(pmv[2].x); pmv[2].y = EVEN(pmv[2].y);
1272    
         pmv[3].x = pmv[3].y = 0;  
1273          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour
1274                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);
1275                  pmv[3].x = EVEN(pmv[3].x); pmv[3].y = EVEN(pmv[3].y); }                  pmv[3].x = EVEN(pmv[3].x); pmv[3].y = EVEN(pmv[3].y);
1276            } else pmv[3].x = pmv[3].y = 0;
1277    
1278          if (y != 0) {          if (y != 0) {
1279                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);
# Line 929  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;
   
         Data.iMinSAD = &iMinSAD;  
         Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
         Data.iEdgedWidth = iEdgedWidth;  
         Data.currentMV = &currentMV;  
         Data.iMinSAD = &iMinSAD;  
         Data.Ref = pRef + (x + y * iEdgedWidth) * 16;  
         Data.RefH = pRefH + (x + y * iEdgedWidth) * 16;  
         Data.RefV = pRefV + (x + y * iEdgedWidth) * 16;  
         Data.RefHV = pRefHV + (x + y * iEdgedWidth) * 16;  
   
         Data.iQuant = iQuant;  
         Data.iFcode = iFcode;  
         Data.predMV = *predMV;  
1322    
1323          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,          Data->Ref = pRef + (x + y * iEdgedWidth) * 16;
1324                                  pParam->width, pParam->height, iFcode);          Data->RefH = pRefH + (x + y * iEdgedWidth) * 16;
1325            Data->RefV = pRefV + (x + y * iEdgedWidth) * 16;
1326            Data->RefHV = pRefHV + (x + y * iEdgedWidth) * 16;
1327    
1328          if (!(MotionFlags & PMV_HALFPEL16)) {          Data->predMV = *predMV;
                 Data.min_dx = EVEN(Data.min_dx);  
                 Data.max_dx = EVEN(Data.max_dx);  
                 Data.min_dy = EVEN(Data.min_dy);  
                 Data.max_dy = EVEN(Data.max_dy); } // no-halpel and b-frames. do we need it?  
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 990  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  }  }
1371    
1372  static int32_t  static int32_t
1373  SearchDirect(const uint8_t * const f_Ref,  SearchDirect(const IMAGE * const f_Ref,
1374                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1375                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
1376                                  const uint8_t * const f_RefHV,                                  const uint8_t * const f_RefHV,
1377                                  const uint8_t * const b_Ref,                                  const IMAGE * const b_Ref,
1378                                  const uint8_t * const b_RefH,                                  const uint8_t * const b_RefH,
1379                                  const uint8_t * const b_RefV,                                  const uint8_t * const b_RefV,
1380                                  const uint8_t * const b_RefHV,                                  const uint8_t * const b_RefHV,
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 = 0, 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 + (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 + (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;
   
         if (( pMB->mvs[k].x > Data.max_dx ) || ( pMB->mvs[k].x < Data.min_dx )  
                         || ( pMB->mvs[k].y > Data.max_dy ) || ( pMB->mvs[k].y < Data.min_dy )  
                         || ( pMB->b_mvs[k].x > Data.max_dx ) || ( pMB->b_mvs[k].x < Data.min_dx )  
                         || ( pMB->b_mvs[k].y > Data.max_dy ) || ( pMB->b_mvs[k].y < Data.min_dy )) {  
 /*  
                 fprintf(debug, "\nERROR - out of range : vector %d,%d and %d,%d\n", pMB->mvs[k].x, pMB->mvs[k].y,pMB->b_mvs[k].x,pMB->b_mvs[k].y );  
                 fprintf(debug, " range is x: %d..%d y: %d..%d \n", Data.min_dx,Data.max_dx,Data.min_dy,Data.max_dy);  
                 fprintf(debug,"macroblock %d, %d \n", x, y);  
                 fprintf(debug, "direct MV is %d,%d \n", directmv[k].x, directmv[k].y);  
 */  
                 *best_sad = 256*4096; // in that case, we won't use direct mode  
                 pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"  
                 pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;  /* because backwards and interpol might rely on this */  
                 return 0; }  
1419    
1420                    if ( ( pMB->b_mvs[k].x > Data->max_dx ) || ( pMB->b_mvs[k].x < Data->min_dx )
1421                            || ( 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
1424                            pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
1425                            pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;
1426                            return 0;
1427                    }
1428          if (b_mb->mode != MODE_INTER4V) {          if (b_mb->mode != MODE_INTER4V) {
1429                  iMinSAD = sad16bi(Data.Cur,                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1430                                                  get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,                          pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];
1431                                                                  x, y, 16, &pMB->mvs[0], iEdgedWidth),                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1432                                                  get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1433                                                                  x, y, 16, &pMB->b_mvs[0], iEdgedWidth), iEdgedWidth);                          break;
1434                    }
                 Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];  
                 Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];  
                 break;  
         }  
         iMinSAD += sad8bi(Data.Cur + (k&1)*8 + (k>>1)* 8 * iEdgedWidth,  
                                                 get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,  
                                                                 (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->mvs[k], iEdgedWidth),  
                                                 get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,  
                                                                 (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->b_mvs[k], iEdgedWidth),  
                                                 iEdgedWidth);  
1435          }          }
1436    
 // skip decision  
         if (iMinSAD < (int32_t)iQuant * SKIP_THRESH_B) {  
                 pMB->mode = MODE_DIRECT_NONE_MV;  
                 return iMinSAD; }  
   
         skip_sad = iMinSAD;  
         iMinSAD += 2 * lambda_vec16[iQuant]; // 2 bits needed to code vector 0,0  
         currentMV.x = currentMV.y = 0;  
1437          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1438                  CheckCandidate = CheckCandidateDirect;                  CheckCandidate = CheckCandidateDirect;
1439          else CheckCandidate = CheckCandidateDirectno4v;          else CheckCandidate = CheckCandidateDirectno4v;
1440    
1441            (*CheckCandidate)(0, 0, 255, &k, Data);
1442    
1443    // skip decision
1444            if (*Data->iMinSAD - 2 * Data->lambda16 < (uint32_t)pMB->quant * SKIP_THRESH_B) {
1445                    //possible skip - checking chroma. everything copied from MC
1446                    //this is not full chroma compensation, only it's fullpel approximation. should work though
1447                    int sum, dx, dy, b_dx, b_dy;
1448    
1449                    sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1450                    dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1451    
1452                    sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1453                    dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1454    
1455                    sum = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;
1456                    b_dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1457    
1458                    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));
1460    
1461                    sum = sad8bi(pCur->u + 8*x + 8*y*(Data->iEdgedWidth/2),
1462                                            f_Ref->u + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1463                                            b_Ref->u + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1464                                            Data->iEdgedWidth/2);
1465                    sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1466                                            f_Ref->v + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1467                                            b_Ref->v + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1468                                            Data->iEdgedWidth/2);
1469    
1470                    if (sum < MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) {
1471                            pMB->mode = MODE_DIRECT_NONE_MV;
1472                            return *Data->iMinSAD;
1473                    }
1474            }
1475    
1476            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
1480    
# Line 1123  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 1168  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;  
   
         fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
         fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;  
         fData.currentMV = currentMV; bData.currentMV = currentMV + 1;  
         fData.iQuant = bData.iQuant = iQuant;  
         fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;  
1544    
1545            *(bData.iMinSAD = fData->iMinSAD) = 4096*256;
1546            bData.Cur = fData->Cur;
1547            fData->iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;
1548            bData.currentMV = fData->currentMV + 1;
1549            bData.lambda16 = fData->lambda16;
1550            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1551    
1552            bData.bRef = fData->Ref = f_Ref + (x + y * iEdgedWidth) * 16;
1553            bData.bRefH = fData->RefH = f_RefH + (x + y * iEdgedWidth) * 16;
1554            bData.bRefV = fData->RefV = f_RefV + (x + y * iEdgedWidth) * 16;
1555            bData.bRefHV = fData->RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;
1556            bData.Ref = fData->bRef = b_Ref + (x + y * iEdgedWidth) * 16;
1557            bData.RefH = fData->bRefH = b_RefH + (x + y * iEdgedWidth) * 16;
1558            bData.RefV = fData->bRefV = b_RefV + (x + y * iEdgedWidth) * 16;
1559            bData.RefHV = fData->bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;
1560    
1561            bData.bpredMV = fData->predMV = *f_predMV;
1562            fData->bpredMV = bData.predMV = *b_predMV;
1563    
1564            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, 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, pParam->m_quarterpel);
1567    
1568            if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1569            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dy;
1570            if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dx;
1571            if (fData->currentMV[0].y > fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1572    
1573            if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1574            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dy;
1575            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dx;
1576            if (fData->currentMV[1].y > bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1577    
1578          bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;          CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
         bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;  
         bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;  
         bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;  
         bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;  
         bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;  
         bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;  
         bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;  
   
         bData.bpredMV = fData.predMV = *f_predMV;  
         fData.bpredMV = bData.predMV = *b_predMV;  
   
   
         currentMV[0] = pMB->mvs[0];  
         currentMV[1] = pMB->b_mvs[0];  
         get_range(&fData.min_dx, &fData.max_dx, &fData.min_dy, &fData.max_dy, x, y, 16, pParam->width, pParam->height, fcode);  
         get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode);  
   
         CheckCandidateInt(currentMV[0].x, currentMV[0].y, 255, &iDirection, &fData);  
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 + 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1588                  CheckCandidateInt(i, j + 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1589                  CheckCandidateInt(i - 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1590                  CheckCandidateInt(i, j - 2, 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 + 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1597                  CheckCandidateInt(i, j + 2, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1598                  CheckCandidateInt(i - 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
1599                  CheckCandidateInt(i, j - 2, 0, &iDirection, &bData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, &bData);
1600    
1601          } while (!(iDirection));          } while (!(iDirection));
1602    
 /* halfpel refinement. luckly we can use normal halfpel function for it */  
   
         if (MotionFlags & PMV_HALFPELREFINE16) {  
                 CheckCandidate = CheckCandidateInt;  
                 HalfpelRefine(&fData);  
                 currentMV[2] = currentMV[0];  
                 HalfpelRefine(&bData);  
         }  
   
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 1265  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 1293  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 1309  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    
1678                          skip_sad = SearchDirect(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                          skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
1679                                                                          b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,
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    
                         if (!(frame->global_flags & XVID_HALFPEL)) best_sad = skip_sad = 256*4096;  
                         else  
1689                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1690    
1691  //                      best_sad = 256*4096; //uncomment to disable Directsearch.  //                      best_sad = 256*4096; //uncomment to disable Directsearch.
# Line 1334  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 1354  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 1389  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            if(pParam->m_quarterpel) {
1773                    //it is qpel. substract d_mv_bits[qpel] from 0, add d_mv_bits[hpel] everywhere
1774                    if (block == 0)
1775                            *(Data->iMinSAD) -= Data->lambda8 *
1776                                                                            d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1777                                                                                                    Data->currentQMV->y - Data->predQMV.y,
1778                                                                                                    Data->iFcode);
1779    
1780                    *(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    
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.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
         Data.iMinSAD = OldData->iMinSAD + 1 + block;  
         Data.currentMV = OldData->currentMV+1+block;  
         Data.iFcode = OldData->iFcode;  
         Data.iQuant = OldData->iQuant;  
   
         Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));  
         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));  
   
         CheckCandidate = CheckCandidate8;  
1798    
1799          if (block != 0)          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1800                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *                                  pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
                                                                 d_mv_bits(      Data.currentMV->x - Data.predMV.x,  
                                                                                         Data.currentMV->y - Data.predMV.y,  
                                                                                         Data.iFcode);  
1801    
1802            CheckCandidate = CheckCandidate8;
1803    
1804          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,          temp_sad = *(Data->iMinSAD); // store current MinSAD
                                 pParam->width, pParam->height, OldData->iFcode);  
   
         if (pMB->mode == MODE_INTER4V) {  
                 int dummy;  
                 CheckCandidate8(pMB->mvs[block].x, pMB->mvs[block].y, 0, &dummy, &Data); }  
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          if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                          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          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;                          Data->iMinSAD[0] += Data->lambda8 *
1837          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;                                  d_mv_bits(Data->predQMV.x - Data->currentQMV[0].x, Data->predQMV.y - Data->currentQMV[0].y, Data->iFcode);
1838          pMB->mvs[block] = *(Data.currentMV);  
1839          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                                  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            pMB->mvs[block] = *(Data->currentMV);
1849            pMB->qmvs[block] = *(Data->currentQMV);
1850    
1851            pMB->sad8[block] =  4 * (*Data->iMinSAD);
1852  }  }
1853    
1854    
# Line 1455  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;  
   
         Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);  
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,  
                                 pParam->width, pParam->height, iFcode);  
1876    
1877          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1878          Data.iEdgedWidth = iEdgedWidth;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1879          Data.currentMV = currentMV;                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
1880          Data.iMinSAD = iMinSAD;  
1881          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data->Cur = pCur->y + (x + y * iEdgedWidth) * 16;
1882          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->Ref = pRef + (x + iEdgedWidth*y)*16;
1883          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + iEdgedWidth*y) * 16;
1884          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + iEdgedWidth*y) * 16;
1885          Data.temp = temp;          Data->RefHV = pRefHV + (x + iEdgedWidth*y) * 16;
1886          Data.iQuant = iQuant;          Data->lambda16 = lambda_vec16[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 1505  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 1526  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->mv16 = 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 1568  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    
2015          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
2016                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
                         int32_t sad00;  
2017    
2018                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2019    
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                          if (pMB->dquant == NO_CHANGE) //no skip otherwise, anyway                          SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
2036                                  sad00 = pMB->sad16                                                          y, current->motion_flags, pMB->quant,
2037                                          = sad16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
2038                                                                  pRef->y + (x + y * pParam->edged_width) * 16,                                                          &Data);
                                                                 pParam->edged_width, 256*4096 );  
                         else sad00 = 256*4096;  
2039    
2040                    }
2041            }
2042            free(qimage);
2043    }
2044    
2045  //initial skip decision  static __inline int
2046    MEanalyzeMB (   const uint8_t * const pRef,
2047                                    const uint8_t * const pCur,
2048                                    const int x,
2049                                    const int y,
2050                                    const MBParam * const pParam,
2051                                    const MACROBLOCK * const pMBs,
2052                                    MACROBLOCK * const pMB,
2053                                    SearchData * const Data)
2054    {
2055    
2056                          if ( (pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)          int i, mask;
2057                                  && ( //(pMB->mode == MODE_NOT_CODED) ||          VECTOR pmv[3];
2058                                          (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant) )) ) {  
2059                                  if (sad00 < pMB->quant * INITIAL_SKIP_THRESH) {          *(Data->iMinSAD) = MV_MAX_ERROR;
2060                                          SkipMacroblockP(pMB, sad00);          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
2061                                          continue; } //skipped          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 * pParam->edged_width) * 16;
2065            Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
2066    
2067            CheckCandidate = CheckCandidate16no4vI;
2068    
2069            pmv[1].x = EVEN(pMB->mvs[0].x);
2070            pmv[1].y = EVEN(pMB->mvs[0].y);
2071            pmv[0].x = EVEN(Data->predMV.x);
2072            pmv[0].y = EVEN(Data->predMV.y);
2073            pmv[2].x = pmv[2].y = 0;
2074    
2075            CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, Data);
2076            if (!(mask = make_mask(pmv, 1)))
2077                    CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, Data);
2078            if (!(mask = make_mask(pmv, 2)))
2079                    CheckCandidate16no4vI(0, 0, mask, &i, Data);
2080    
2081            DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, mask);
2082    
2083            pMB->mvs[0] = pMB->mvs[1]
2084                            = pMB->mvs[2] = pMB->mvs[3] = *Data->currentMV; // all, for future get_pmv()
2085    
2086            return *(Data->iMinSAD);
2087                          }                          }
                         else sad00 = 256*4096;  
2088    
2089                          if (pMB->mode == MODE_NOT_CODED)  #define INTRA_THRESH    1350
2090                                  SearchP(        pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,  #define INTER_THRESH    900
                                                         y, current->motion_flags, pMB->quant,  
                                                         current->fcode, pParam, pMBs, reference->mbs,  
                                                         current->global_flags & XVID_INTER4V, pMB);  
2091    
2092                          else  int
2093                                  SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,  MEanalysis(     const IMAGE * const pRef,
2094                                                          y, current->motion_flags, pMB->quant,                          const IMAGE * const pCurrent,
2095                                                          current->fcode, pParam, pMBs,                          MBParam * const pParam,
2096                                                          current->global_flags & XVID_INTER4V, pMB);                          MACROBLOCK * const pMBs,
2097                            const uint32_t iFcode)
2098    {
2099            uint32_t x, y, intra = 0;
2100            int sSAD = 0;
2101    
2102  /* final skip decision, a.k.a. "the vector you found, really that good?" */          VECTOR currentMV;
2103                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)          int32_t iMinSAD;
2104                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)          SearchData Data;
2105                                  SkipMacroblockP(pMB, sad00);          Data.iEdgedWidth = pParam->edged_width;
2106            Data.currentMV = &currentMV;
2107            Data.iMinSAD = &iMinSAD;
2108            Data.iFcode = iFcode;
2109    
2110            if (sadInit) (*sadInit) ();
2111    
2112            for (y = 1; y < pParam->mb_height-1; y++) {
2113                    for (x = 1; x < pParam->mb_width-1; x++) {
2114                            int sad, dev;
2115                            MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2116    
2117                            sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
2118                                                                    pParam, pMBs, pMB, &Data);
2119    
2120                            if (sad > INTRA_THRESH) {
2121                                    dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
2122                                                              pParam->edged_width);
2123                                    if (dev + INTRA_THRESH < sad) intra++;
2124                                    if (intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame
2125                                    }
2126                            sSAD += sad;
2127                  }                  }
2128          }          }
2129            sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2130            if (sSAD > INTER_THRESH ) return 1; //P frame
2131            emms();
2132            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.530  
changed lines
  Added in v.601

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