[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 600, Thu Oct 17 13:27:22 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 = data->Ref + (X)/2 + ((Y)/2)*(data->iEdgedWidth); break; \
59                    case 1 : REF = data->RefV + (X)/2 + (((Y)-1)/2)*(data->iEdgedWidth); break; \
60                    case 2 : REF = data->RefH + ((X)-1)/2 + ((Y)/2)*(data->iEdgedWidth); break; \
61                    default : REF = 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            if(data->quarterpel)
114                    t = d_mv_bits(2*x - data->predQMV.x, 2*y - data->predQMV.y, data->iFcode);
115            else
116          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);
117    
118          data->temp[0] += lambda_vec16[data->iQuant] * t;          data->temp[0] += lambda_vec16[data->iQuant] * t;
119          data->temp[1] += lambda_vec8[data->iQuant] * t;          data->temp[1] += lambda_vec8[data->iQuant] * t;
120    
# Line 138  Line 151 
151                  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;
152          }          }
153    
154            if(data->quarterpel)
155                    sad = lambda_vec16[data->iQuant] *
156                          d_mv_bits(2*x - data->predQMV.x, 2*y - data->predQMV.y, data->iFcode);
157            else
158          sad = lambda_vec16[data->iQuant] *          sad = lambda_vec16[data->iQuant] *
159                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
160          sad += sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);  
161            sad += sad16(data->Cur, Reference, data->iEdgedWidth, MV_MAX_ERROR);
162    
163          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
164                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 149  Line 167 
167  }  }
168    
169  static void  static void
170    CheckCandidate16_qpel(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
171    
172    // CheckCandidate16 variant which expects x and y in quarter pixel resolution
173    // Important: This is no general usable routine! x and y must be +/-1 (qpel resolution!)
174    // around currentMV!
175    {
176            int t;
177            uint8_t * Reference = (uint8_t *) data->RefQ;
178            const uint8_t *ref1, *ref2, *ref3, *ref4;
179            VECTOR halfpelMV = *(data->currentMV);
180    
181            int32_t iEdgedWidth = data->iEdgedWidth;
182            uint32_t rounding = data->rounding;
183    
184            if (( x > data->max_dx) || ( x < data->min_dx)
185                    || ( y > data->max_dy) || (y < data->min_dy)) return;
186    
187            switch( ((x&1)<<1) + (y&1) )
188            {
189            case 0: // pure halfpel position - shouldn't happen during a refinement step
190                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, (const uint8_t *) Reference);
191                    break;
192    
193            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
194                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
195                    GET_REFERENCE(halfpelMV.x, y - 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            case 2: // x qpel, y halfpel - left or right during qpel refinement
204                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
205                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref2);
206    
207                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
208                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding);
209                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding);
210                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding);
211                    break;
212    
213            default: // x and y in qpel resolution - the "corners" (top left/right and
214                             // bottom left/right) during qpel refinement
215                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
216                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
217                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref3);
218                    GET_REFERENCE(x - halfpelMV.x, y - halfpelMV.y, ref4);
219    
220                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
221                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
222                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
223                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
224                    break;
225            }
226    
227            data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp+1);
228    
229            t = d_mv_bits(x - data->predQMV.x, y - data->predQMV.y, data->iFcode);
230            data->temp[0] += lambda_vec16[data->iQuant] * t;
231            data->temp[1] += lambda_vec8[data->iQuant] * t;
232    
233            if (data->temp[0] < data->iMinSAD[0]) {
234                    data->iMinSAD[0] = data->temp[0];
235                    data->currentQMV[0].x = x; data->currentQMV[0].y = y;
236            /*      *dir = Direction;*/ }
237    
238            if (data->temp[1] < data->iMinSAD[1]) {
239                    data->iMinSAD[1] = data->temp[1]; data->currentQMV[1].x = x; data->currentQMV[1].y = y; }
240            if (data->temp[2] < data->iMinSAD[2]) {
241                    data->iMinSAD[2] = data->temp[2]; data->currentQMV[2].x = x; data->currentQMV[2].y = y; }
242            if (data->temp[3] < data->iMinSAD[3]) {
243                    data->iMinSAD[3] = data->temp[3]; data->currentQMV[3].x = x; data->currentQMV[3].y = y; }
244            if (data->temp[4] < data->iMinSAD[4]) {
245                    data->iMinSAD[4] = data->temp[4]; data->currentQMV[4].x = x; data->currentQMV[4].y = y; }
246    }
247    
248    static void
249    CheckCandidate16no4v_qpel(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
250    
251    // CheckCandidate16no4v variant which expects x and y in quarter pixel resolution
252    // Important: This is no general usable routine! x and y must be +/-1 (qpel resolution!)
253    // around currentMV!
254    {
255            int32_t sad;
256            uint8_t * Reference = (uint8_t *) data->RefQ;
257            const uint8_t *ref1, *ref2, *ref3, *ref4;
258            VECTOR halfpelMV = *(data->currentMV);
259    
260            int32_t iEdgedWidth = data->iEdgedWidth;
261            uint32_t rounding = data->rounding;
262    
263            if (( x > data->max_dx) || ( x < data->min_dx)
264                    || ( y > data->max_dy) || (y < data->min_dy)) return;
265    
266            switch( ((x&1)<<1) + (y&1) )
267            {
268            case 0: // pure halfpel position - shouldn't happen during a refinement step
269                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, (const uint8_t *) Reference);
270                    break;
271    
272            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
273                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
274                    GET_REFERENCE(halfpelMV.x, y - 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            case 2: // x qpel, y halfpel - left or right during qpel refinement
283                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
284                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref2);
285    
286                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
287                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding);
288                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding);
289                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding);
290                    break;
291    
292            default: // x and y in qpel resolution - the "corners" (top left/right and
293                             // bottom left/right) during qpel refinement
294                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
295                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
296                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref3);
297                    GET_REFERENCE(x - halfpelMV.x, y - halfpelMV.y, ref4);
298    
299                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
300                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
301                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
302                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
303                    break;
304            }
305    
306            sad = lambda_vec16[data->iQuant] *
307                            d_mv_bits(x - data->predQMV.x, y - data->predQMV.y, data->iFcode);
308            sad += sad16(data->Cur, Reference, data->iEdgedWidth, MV_MAX_ERROR);
309    
310            if (sad < *(data->iMinSAD)) {
311                    *(data->iMinSAD) = sad;
312                    data->currentQMV[0].x = x; data->currentQMV[0].y = y;
313    //              *dir = Direction;
314            }
315    }
316    
317    static void
318    CheckCandidate16no4vI(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
319    {
320            int32_t sad;
321    
322            if (( x > data->max_dx) || ( x < data->min_dx)
323                    || ( y > data->max_dy) || (y < data->min_dy)) return;
324    
325            sad = lambda_vec16[data->iQuant] *
326                            d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
327    
328            sad += sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),
329                                            data->iEdgedWidth, 256*4096);
330    
331            if (sad < *(data->iMinSAD)) {
332                    *(data->iMinSAD) = sad;
333                    data->currentMV[0].x = x; data->currentMV[0].y = y;
334                    *dir = Direction; }
335    }
336    
337    
338    static void
339  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)
340  {  {
341          int32_t sad;          int32_t sad;
# Line 249  Line 436 
436          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
437          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
438    
439          if (( x > 31) || ( x < -31) || ( y > 31) || (y < -31)) return;          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
440    
441                  sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);                  sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);
442    
# Line 308  Line 495 
495          }          }
496    
497          sad = sad8(data->Cur, Reference, data->iEdgedWidth);          sad = sad8(data->Cur, Reference, data->iEdgedWidth);
498    
499            if(data->quarterpel)
500                    sad += lambda_vec8[data->iQuant] * d_mv_bits(2*x - data->predQMV.x, 2*y - data->predQMV.y, data->iFcode);
501            else
502          sad += lambda_vec8[data->iQuant] * d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          sad += lambda_vec8[data->iQuant] * d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
503    
504          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
# Line 316  Line 507 
507                  *dir = Direction; }                  *dir = Direction; }
508  }  }
509    
510  /* CHACK_CANDIATE FUNCTIONS END */  static void
511    CheckCandidate8_qpel(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
512    // CheckCandidate16no4v variant which expects x and y in quarter pixel resolution
513    // Important: This is no general usable routine! x and y must be +/-1 (qpel resolution!)
514    // around currentMV!
515    
516    {
517            int32_t sad;
518            uint8_t *Reference = (uint8_t *) data->RefQ;
519            const uint8_t *ref1, *ref2, *ref3, *ref4;
520            VECTOR halfpelMV = *(data->currentMV);
521    
522            int32_t iEdgedWidth = data->iEdgedWidth;
523            uint32_t rounding = data->rounding;
524    
525            if (( x > data->max_dx) || ( x < data->min_dx)
526                    || ( y > data->max_dy) || (y < data->min_dy)) return;
527    
528            switch( ((x&1)<<1) + (y&1) )
529            {
530            case 0: // pure halfpel position - shouldn't happen during a refinement step
531                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, (const uint8_t *) Reference);
532                    break;
533    
534            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
535                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
536                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
537    
538                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
539                    break;
540    
541            case 2: // x qpel, y halfpel - left or right during qpel refinement
542                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
543                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref2);
544    
545                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
546                    break;
547    
548            default: // x and y in qpel resolution - the "corners" (top left/right and
549                             // bottom left/right) during qpel refinement
550                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
551                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
552                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref3);
553                    GET_REFERENCE(x - halfpelMV.x, y - halfpelMV.y, ref4);
554    
555                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
556                    break;
557            }
558    
559            sad = sad8(data->Cur, Reference, data->iEdgedWidth);
560            sad += lambda_vec8[data->iQuant] * d_mv_bits(x - data->predQMV.x, y - data->predQMV.y, data->iFcode);
561    
562            if (sad < *(data->iMinSAD)) {
563                    *(data->iMinSAD) = sad;
564                    data->currentQMV->x = x; data->currentQMV->y = y;
565                    *dir = Direction; }
566    }
567    
568    /* CHECK_CANDIATE FUNCTIONS END */
569    
570  /* MAINSEARCH FUNCTIONS START */  /* MAINSEARCH FUNCTIONS START */
571    
# Line 484  Line 733 
733          CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);          CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);
734  }  }
735    
736    
737    static void
738    QuarterpelRefine(const SearchData * const data)
739    {
740    /* Perform quarter pixel refinement*/
741    
742            VECTOR backupMV = *(data->currentQMV);
743            int iDirection; //not needed
744    
745            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);
746            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);
747            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);
748            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y + 1, 0);
749    
750            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y, 0);
751            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y, 0);
752    
753            CHECK_CANDIDATE(backupMV.x, backupMV.y + 1, 0);
754            CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);
755    
756    }
757    
758  static __inline int  static __inline int
759  SkipDecisionP(const IMAGE * current, const IMAGE * reference,  SkipDecisionP(const IMAGE * current, const IMAGE * reference,
760                                                          const int x, const int y,                                                          const int x, const int y,
# Line 497  Line 768 
768          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,
769                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);
770          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
771          sadC += sad8(current->v + x*8 + y*(iEdgedWidth/2)*8,          sadC += sad8(current->v + (x + y*(iEdgedWidth/2))*8,
772                                          reference->v + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                          reference->v + (x + y*(iEdgedWidth/2))*8, iEdgedWidth/2);
773          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
774    
775          return 1;          return 1;
# Line 508  Line 779 
779  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)
780  {  {
781          pMB->mode = MODE_NOT_CODED;          pMB->mode = MODE_NOT_CODED;
782          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;
783          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;
784    
785            pMB->qmvs[0].x = pMB->qmvs[1].x = pMB->qmvs[2].x = pMB->qmvs[3].x = 0;
786            pMB->qmvs[0].y = pMB->qmvs[1].y = pMB->qmvs[2].y = pMB->qmvs[3].y = 0;
787    
788          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;
789  }  }
790    
# Line 530  Line 805 
805    
806          uint32_t x, y;          uint32_t x, y;
807          uint32_t iIntra = 0;          uint32_t iIntra = 0;
808          int32_t InterBias;          int32_t InterBias, quant = current->quant;
809            uint8_t *qimage;
810    
811            // some pre-initialized thingies for SearchP
812            int32_t temp[5];
813            VECTOR currentMV[5];
814            VECTOR currentQMV[5];
815            int32_t iMinSAD[5];
816            SearchData Data;
817            Data.iEdgedWidth = pParam->edged_width;
818            Data.currentMV = currentMV;
819            Data.currentQMV = currentQMV;
820            Data.iMinSAD = iMinSAD;
821            Data.temp = temp;
822            Data.iFcode = current->fcode;
823            Data.rounding = pParam->m_rounding_type;
824            Data.quarterpel = pParam->m_quarterpel;
825    
826            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
827                    return 1; // allocate some mem for qpel interpolated blocks
828                                      // somehow this is dirty since I think we shouldn't use malloc outside
829                                      // encoder_create() - so please fix me!
830    
831          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
832    
# Line 546  Line 842 
842                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
843                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
844                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant; }
845                            else
846                                    if (pMB->dquant != NO_CHANGE) {
847                                            quant += DQtab[pMB->dquant];
848                                            if (quant > 31) quant = 31;
849                                            else if (quant < 1) quant = 1;
850                                            pMB->quant = quant;
851                                    }
852    
853  //initial skip decision  //initial skip decision
854    
# Line 554  Line 857 
857                                  if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {                                  if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {
858                                                  SkipMacroblockP(pMB, sad00);                                                  SkipMacroblockP(pMB, sad00);
859                                                  continue;                                                  continue;
860                                            sad00 = 256 * 4096;
861                                  }                                  }
862                          } else sad00 = 256*4096; // skip not allowed - for final skip decision                          } else sad00 = 256*4096; // skip not allowed - for final skip decision
863    
864                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, qimage, pCurrent, x,
865                                                  y, current->motion_flags, pMB->quant,                                                  y, current->motion_flags, pMB->quant,
866                                                  current->fcode, pParam, pMBs, reference->mbs,                                                  &Data, pParam, pMBs, reference->mbs,
867                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
868    
869  /* 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?" */
# Line 582  Line 886 
886                                                    pParam->edged_width);                                                    pParam->edged_width);
887    
888                                  if (deviation < (pMB->sad16 - InterBias)) {                                  if (deviation < (pMB->sad16 - InterBias)) {
889                                          if (++iIntra >= iLimit) return 1;                                          if (++iIntra >= iLimit) { free(qimage); return 1; }
890                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
891                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
892                                                  pMB->mvs[3] = zeroMV;                                                  pMB->mvs[3] = zeroMV;
893                                            pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] =
894                                                            pMB->qmvs[3] = zeroMV;
895                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
896                                                  pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
897                                  }                                  }
898                          }                          }
899                  }                  }
900          }          }
901            free(qimage);
902          return 0;          return 0;
903  }  }
904    
# Line 601  Line 908 
908  static __inline int  static __inline int
909  make_mask(const VECTOR * const pmv, const int i)  make_mask(const VECTOR * const pmv, const int i)
910  {  {
911          int mask = 0xFF, j;          int mask = 255, j;
912          for (j = 0; j < i; j++) {          for (j = 0; j < i; j++) {
913                  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
914                  if (pmv[i].x == pmv[j].x) {                  if (pmv[i].x == pmv[j].x) {
# Line 625  Line 932 
932    
933          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour
934                  pmv[5].x = EVEN(pmv[3].x);                  pmv[5].x = EVEN(pmv[3].x);
935                  pmv[5].y = EVEN(pmv[3].y); }                  pmv[5].y = EVEN(pmv[3].y);
936          else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
937    
938          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
939          else pmv[3].x = pmv[3].y = 0;          else pmv[3].x = pmv[3].y = 0;
# Line 644  Line 951 
951    
952          if ((x != iWcount-1) && (y != iHcount-1)) {          if ((x != iWcount-1) && (y != iHcount-1)) {
953                  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
954                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y); }                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
955          else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
956  }  }
957    
958  static void  static void
# Line 653  Line 960 
960                  const uint8_t * const pRefH,                  const uint8_t * const pRefH,
961                  const uint8_t * const pRefV,                  const uint8_t * const pRefV,
962                  const uint8_t * const pRefHV,                  const uint8_t * const pRefHV,
963                    const uint8_t * const pRefQ,
964                  const IMAGE * const pCur,                  const IMAGE * const pCur,
965                  const int x,                  const int x,
966                  const int y,                  const int y,
967                  const uint32_t MotionFlags,                  const uint32_t MotionFlags,
968                  const uint32_t iQuant,                  const uint32_t iQuant,
969                  const uint32_t iFcode,                  SearchData * const Data,
970                  const MBParam * const pParam,                  const MBParam * const pParam,
971                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
972                  const MACROBLOCK * const prevMBs,                  const MACROBLOCK * const prevMBs,
# Line 666  Line 974 
974                  MACROBLOCK * const pMB)                  MACROBLOCK * const pMB)
975  {  {
976    
         const int32_t iEdgedWidth = pParam->edged_width;  
   
977          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
978          int32_t temp[5];          VECTOR pmv[7];
         VECTOR currentMV[5], pmv[7];  
         int32_t psad[4], iMinSAD[5];  
         MainSearchFunc * MainSearchPtr;  
         SearchData Data;  
979    
980          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;  
981    
982          Data.iQuant = iQuant;          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()
983          Data.iFcode = iFcode;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
984                                    pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
985    
986            Data->predMV = pmv[0];
987    
988            Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
989            Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;
990            Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
991            Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
992            Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
993            Data->RefQ = pRefQ;
994    
995            Data->iQuant = iQuant;
996    
997          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
998                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
999                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
1000                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
1001                  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];  
1002    
1003          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
1004    
1005            if (inter4v) CheckCandidate = CheckCandidate16;
1006            else CheckCandidate = CheckCandidate16no4v;
1007    
1008            for(i = 0;  i < 5; i++)
1009                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
1010    
1011            if(Data->quarterpel)
1012                    i = d_mv_bits(Data->predQMV.x, Data->predQMV.y, Data->iFcode);
1013            else
1014                    i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);
1015    
1016            Data->iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;
1017            Data->iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;
1018            Data->iMinSAD[2] = pMB->sad8[1];
1019            Data->iMinSAD[3] = pMB->sad8[2];
1020            Data->iMinSAD[4] = pMB->sad8[3];
1021    
1022          if ((x == 0) && (y == 0)) threshA = 512;          if ((x == 0) && (y == 0)) threshA = 512;
1023          else {          else {
1024                  threshA = psad[0] + 20;                  threshA = Data->temp[0]; // that's when we keep this SAD atm
1025                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
1026                  if (threshA > 1024) threshA = 1024; }                  if (threshA > 1024) threshA = 1024; }
1027    
# Line 723  Line 1031 
1031          if (inter4v) CheckCandidate = CheckCandidate16;          if (inter4v) CheckCandidate = CheckCandidate16;
1032          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
1033    
1034    
1035  /* main loop. checking all predictions */  /* main loop. checking all predictions */
1036    
1037          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
1038                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1039                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  (*CheckCandidate)(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1040                  if (iMinSAD[0] < threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1041          }          }
1042    
1043          if ((iMinSAD[0] <= threshA) ||          if ((Data->iMinSAD[0] <= threshA) ||
1044                          (MVequal(currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
1045                          (iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {                          (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {
1046                  inter4v = 0;                  inter4v = 0;
1047                  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;  
                 }  
         }  
1048    
1049          if (MotionFlags & PMV_USESQUARES16)                  MainSearchFunc * MainSearchPtr;
1050                  MainSearchPtr = SquareSearch;                  if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
1051          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
                 MainSearchPtr = AdvDiamondSearch;  
1052                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1053    
1054          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, iDirection);                  (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1055    
1056  /* extended search, diamond starting in 0,0 and in prediction.  /* extended search, diamond starting in 0,0 and in prediction.
1057          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 1059 
1059    
1060          if (MotionFlags & PMV_EXTSEARCH16) {          if (MotionFlags & PMV_EXTSEARCH16) {
1061                  int32_t bSAD;                  int32_t bSAD;
1062                  VECTOR startMV = Data.predMV, backupMV = currentMV[0];                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
1063                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?
1064                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);
1065                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1066                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1067    
1068                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, Data);
1069                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1070                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1071                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1072                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1073                  }                  }
1074    
1075                  backupMV = currentMV[0];                          backupMV = Data->currentMV[0];
1076                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;
1077                  else startMV.x = startMV.y = 0;                  else startMV.x = startMV.y = 0;
1078                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1079                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1080    
1081                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, Data);
1082                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1083                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1084                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1085                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1086                            }
1087                  }                  }
1088          }          }
1089    
1090  PMVfast16_Terminate_with_Refine:          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1091    
1092          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          for(i = 0; i < 5; i++) {
1093                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1094                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1095            }
1096    
1097  PMVfast16_Terminate_without_Refine:          if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1098    
1099          if (inter4v)          if (inter4v)
1100                  for(i = 0; i < 4; i++)                          CheckCandidate = CheckCandidate16_qpel;
1101                          Search8(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                  else
1102                            CheckCandidate = CheckCandidate16no4v_qpel;
1103    
1104                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1105                                      pParam->width, pParam->height, Data->iFcode, 0); // get real range
1106    
1107                    QuarterpelRefine(Data);
1108            }
1109    
1110            if (inter4v) {
1111                    SearchData Data8;
1112                    Data8.iFcode = Data->iFcode;
1113                    Data8.iQuant = Data->iQuant;
1114                    Data8.iEdgedWidth = Data->iEdgedWidth;
1115                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1116                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1117                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1118                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1119            }
1120    
1121          if (!(inter4v) ||          if (!(inter4v) ||
1122                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
1123                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1124  // INTER MODE  // INTER MODE
1125                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1126                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1127                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1128    
1129                    pMB->qmvs[0] = pMB->qmvs[1]
1130                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1131    
1132                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1133                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1134    
1135                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1136                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predQMV.x;
1137                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predQMV.y;
1138                    }
1139                    else {
1140                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1141                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1142                    }
1143          } else {          } else {
1144  // INTER4V MODE; all other things are already set in Search8  // INTER4V MODE; all other things are already set in Search8
1145                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1146                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1147                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1148          }          }
   
1149  }  }
1150    
1151  static void  static void
# Line 820  Line 1155 
1155                  const MBParam * const pParam,                  const MBParam * const pParam,
1156                  MACROBLOCK * const pMB,                  MACROBLOCK * const pMB,
1157                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
1158                  const int block)                  const int block,
1159                    SearchData * const Data)
1160  {  {
1161          SearchData Data;          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1162            Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1163          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1164          Data.iMinSAD = OldData->iMinSAD + 1 + block;          Data->currentMV = OldData->currentMV + 1 + block;
1165          Data.currentMV = OldData->currentMV+1+block;          Data->currentQMV = OldData->currentQMV + 1 + block;
1166          Data.iFcode = OldData->iFcode;          Data->quarterpel = OldData->quarterpel;
         Data.iQuant = OldData->iQuant;  
1167    
1168            if(Data->quarterpel) // add d_mv_bits[qpel] everywhere but not in 0 (it's already there)
1169            {
1170          if (block != 0)          if (block != 0)
1171                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *                          *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *
1172                                                                  d_mv_bits(      Data.currentMV->x - Data.predMV.x,                                                                  d_mv_bits(Data->currentQMV->x - Data->predQMV.x,
1173                                                                                          Data.currentMV->y - Data.predMV.y,                                                                                    Data->currentQMV->y - Data->predQMV.y,
1174                                                                                          Data.iFcode);                                                                                    Data->iFcode);
1175    
1176            } else // add d_mv_bits[hpel] everywhere but not in 0 (it's already there)
1177                    if (block != 0)
1178                            *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *
1179                                                                    d_mv_bits(Data->currentMV->x - Data->predMV.x,
1180                                                                                      Data->currentMV->y - Data->predMV.y,
1181                                                                                      Data->iFcode);
1182    
1183          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
1184    
1185                  Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));
1186                  Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));
1187                  Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1188                  Data.RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1189                    Data->RefQ = OldData->RefQ;
                 Data.iEdgedWidth = pParam->edged_width;  
1190    
1191                  Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
1192    
1193                  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,
1194                                  pParam->width, pParam->height, OldData->iFcode);                                  pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1195    
1196                  CheckCandidate = CheckCandidate8;                  CheckCandidate = CheckCandidate8;
1197    
1198                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & PMV_EXTSEARCH8) {
1199                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1200    
1201                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1202                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1203                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1204                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1205    
1206                          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);     }                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1207    
1208                            if(*(Data->iMinSAD) < temp_sad) { //found a better match?
1209                                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1210                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1211                            }
1212                    }
1213    
1214                    if (MotionFlags & PMV_HALFPELREFINE8) {
1215                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1216    
1217                            HalfpelRefine(Data); // perform halfpel refine of current best vector
1218    
1219                            if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1220                                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1221                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1222                            }
1223                    }
1224    
1225                    if((Data->quarterpel) && (!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1226                       (MotionFlags & PMV_QUARTERPELREFINE8)) {
1227    
1228                            CheckCandidate = CheckCandidate8_qpel;
1229    
1230                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1231                                    pParam->width, pParam->height, OldData->iFcode, 0); // get real range
1232    
1233                            QuarterpelRefine(Data);
1234                    }
1235            }
1236    
1237            if(pParam->m_quarterpel) {
1238                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predQMV.x;
1239                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predQMV.y;
1240          }          }
1241            else {
1242                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1243                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1244            }
1245    
1246            pMB->mvs[block] = *(Data->currentMV);
1247            pMB->qmvs[block] = *(Data->currentQMV);
1248    
1249          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;          pMB->sad8[block] =  4 * (*Data->iMinSAD); // Isibaar: why?
         pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;  
         pMB->mvs[block] = *(Data.currentMV);  
         pMB->sad8[block] =  4 * (*(Data.iMinSAD));  
1250  }  }
1251    
1252  /* B-frames code starts here */  /* B-frames code starts here */
# Line 896  Line 1274 
1274          pmv[2] = ChoosePred(pMB, mode_curr);          pmv[2] = ChoosePred(pMB, mode_curr);
1275          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);
1276    
         pmv[3].x = pmv[3].y = 0;  
1277          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour
1278                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);
1279                  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);
1280            } else pmv[3].x = pmv[3].y = 0;
1281    
1282          if (y != 0) {          if (y != 0) {
1283                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);
# Line 929  Line 1307 
1307                          const IMAGE * const pCur,                          const IMAGE * const pCur,
1308                          const int x, const int y,                          const int x, const int y,
1309                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
1310                          const uint32_t iFcode,                          const uint32_t iFcode,
1311                          const MBParam * const pParam,                          const MBParam * const pParam,
1312                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
1313                          const VECTOR * const predMV,                          const VECTOR * const predMV,
1314                          int32_t * const best_sad,                          int32_t * const best_sad,
1315                          const int32_t mode_current)                          const int32_t mode_current,
1316                            SearchData * const Data)
1317  {  {
1318    
1319          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1320    
1321          int i, iDirection, mask;          int i, iDirection, mask;
1322          VECTOR currentMV, pmv[7];          VECTOR pmv[7];
1323          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1324          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
1325          SearchData Data;          Data->iFcode = iFcode;
1326    
1327          Data.iMinSAD = &iMinSAD;          Data->Ref = pRef + (x + y * iEdgedWidth) * 16;
1328          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->RefH = pRefH + (x + y * iEdgedWidth) * 16;
1329          Data.iEdgedWidth = iEdgedWidth;          Data->RefV = pRefV + (x + y * iEdgedWidth) * 16;
1330          Data.currentMV = &currentMV;          Data->RefHV = pRefHV + (x + y * iEdgedWidth) * 16;
         Data.iMinSAD = &iMinSAD;  
         Data.Ref = pRef + (x + y * iEdgedWidth) * 16;  
         Data.RefH = pRefH + (x + y * iEdgedWidth) * 16;  
         Data.RefV = pRefV + (x + y * iEdgedWidth) * 16;  
         Data.RefHV = pRefHV + (x + y * iEdgedWidth) * 16;  
1331    
1332          Data.iQuant = iQuant;          Data->predMV = *predMV;
         Data.iFcode = iFcode;  
         Data.predMV = *predMV;  
1333    
1334          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1335                                  pParam->width, pParam->height, iFcode);                                  pParam->width, pParam->height, iFcode, pParam->m_quarterpel);
   
         if (!(MotionFlags & PMV_HALFPEL16)) {  
                 Data.min_dx = EVEN(Data.min_dx);  
                 Data.max_dx = EVEN(Data.max_dx);  
                 Data.min_dy = EVEN(Data.min_dy);  
                 Data.max_dy = EVEN(Data.max_dy); } // no-halpel and b-frames. do we need it?  
1336    
1337            pmv[0] = Data->predMV;
1338            PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
1339    
1340          pmv[0] = Data.predMV;          Data->currentMV->x = Data->currentMV->y = 0;
         PreparePredictionsBF(pmv, x, y, pParam->mb_width,  
                                         pMB, mode_current);  
   
         currentMV.x = currentMV.y = 0;  
1341    
1342          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1343    
1344  // main loop. checking all predictions  // main loop. checking all predictions
1345          for (i = 0; i < 8; i++) {          for (i = 0; i < 8; i++) {
1346                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1347                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1348          }          }
1349    
1350          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 990  Line 1353 
1353                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1354                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1355    
1356          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1357    
1358          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          HalfpelRefine(Data);
1359    
1360  // three bits are needed to code backward mode. four for forward  // three bits are needed to code backward mode. four for forward
1361  // we treat the bits just like they were vector's  // we treat the bits just like they were vector's
1362          if (mode_current == MODE_FORWARD) iMinSAD +=  4 * lambda_vec16[iQuant];          if (mode_current == MODE_FORWARD) *Data->iMinSAD +=  4 * lambda_vec16[Data->iQuant];
1363          else iMinSAD +=  3 * lambda_vec16[iQuant];          else *Data->iMinSAD +=  3 * lambda_vec16[Data->iQuant];
1364    
1365    
1366          if (iMinSAD < *best_sad) {          if (*Data->iMinSAD < *best_sad) {
1367                  *best_sad = iMinSAD;                  *best_sad = *Data->iMinSAD;
1368                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1369                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1370                  pMB->pmvs[0].y = currentMV.y - predMV->y;                  pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1371                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = *Data->currentMV;
1372                  else pMB->b_mvs[0] = currentMV;                  else pMB->b_mvs[0] = *Data->currentMV;
1373          }          }
1374    
1375  }  }
1376    
1377  static int32_t  static int32_t
1378  SearchDirect(const uint8_t * const f_Ref,  SearchDirect(const IMAGE * const f_Ref,
1379                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1380                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
1381                                  const uint8_t * const f_RefHV,                                  const uint8_t * const f_RefHV,
1382                                  const uint8_t * const b_Ref,                                  const IMAGE * const b_Ref,
1383                                  const uint8_t * const b_RefH,                                  const uint8_t * const b_RefH,
1384                                  const uint8_t * const b_RefV,                                  const uint8_t * const b_RefV,
1385                                  const uint8_t * const b_RefHV,                                  const uint8_t * const b_RefHV,
1386                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1387                                  const int x, const int y,                                  const int x, const int y,
1388                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1389                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1390                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1391                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1392                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1393                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1394                                    SearchData * const Data)
1395    
1396  {  {
1397          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
         int32_t iMinSAD = 0, skip_sad;  
1398          int k;          int k;
1399          VECTOR currentMV;  
1400          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
         SearchData Data;  
1401    
1402          Data.iMinSAD = &iMinSAD;          *Data->iMinSAD = 256*4096;
1403          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;  
1404    
1405          Data.Ref= f_Ref + (x + iEdgedWidth*y) * 16;          Data->Ref = f_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1406          Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;          Data->RefH = f_RefH + (x + Data->iEdgedWidth*y) * 16;
1407          Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;          Data->RefV = f_RefV + (x + Data->iEdgedWidth*y) * 16;
1408          Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = f_RefHV + (x + Data->iEdgedWidth*y) * 16;
1409          Data.bRef = b_Ref + (x + iEdgedWidth*y) * 16;          Data->bRef = b_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1410          Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;          Data->bRefH = b_RefH + (x + Data->iEdgedWidth*y) * 16;
1411          Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;          Data->bRefV = b_RefV + (x + Data->iEdgedWidth*y) * 16;
1412          Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;          Data->bRefHV = b_RefHV + (x + Data->iEdgedWidth*y) * 16;
1413  /*  
1414  //What we do here is a complicated version of CheckCandidateDirect(0,0);          Data->max_dx = 2 * pParam->width - 2 * (x) * 16;
1415  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;
1416            Data->min_dx = -(2 * 16 + 2 * (x) * 16);
1417  */          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);  
1418    
1419          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1420                  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);
1421                  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;
1422                  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);
1423                  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; }  
1424    
1425                    if ( ( pMB->b_mvs[k].x > Data->max_dx ) || ( pMB->b_mvs[k].x < Data->min_dx )
1426                            || ( pMB->b_mvs[k].y > Data->max_dy ) || ( pMB->b_mvs[k].y < Data->min_dy )) {
1427    
1428                            *best_sad = 256*4096; // in that case, we won't use direct mode
1429                            pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
1430                            pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;
1431                            return 0;
1432                    }
1433          if (b_mb->mode != MODE_INTER4V) {          if (b_mb->mode != MODE_INTER4V) {
1434                  iMinSAD = sad16bi(Data.Cur,                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1435                                                  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];
1436                                                                  x, y, 16, &pMB->mvs[0], iEdgedWidth),                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1437                                                  get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1438                                                                  x, y, 16, &pMB->b_mvs[0], iEdgedWidth), iEdgedWidth);                          break;
1439                    }
                 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);  
1440          }          }
1441    
 // 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;  
1442          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1443                  CheckCandidate = CheckCandidateDirect;                  CheckCandidate = CheckCandidateDirect;
1444          else CheckCandidate = CheckCandidateDirectno4v;          else CheckCandidate = CheckCandidateDirectno4v;
1445    
1446            (*CheckCandidate)(0, 0, 255, &k, Data);
1447    
1448    // skip decision
1449            if (*Data->iMinSAD - 2 * lambda_vec16[Data->iQuant] < (int32_t)Data->iQuant * SKIP_THRESH_B) {
1450                    //possible skip - checking chroma. everything copied from MC
1451                    //this is not full chroma compensation, only it's fullpel approximation. should work though
1452                    int sum, dx, dy, b_dx, b_dy;
1453    
1454                    sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1455                    dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1456    
1457                    sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1458                    dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1459    
1460                    sum = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;
1461                    b_dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1462    
1463                    sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;
1464                    b_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1465    
1466                    sum = sad8bi(pCur->u + 8*x + 8*y*(Data->iEdgedWidth/2),
1467                                            f_Ref->u + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1468                                            b_Ref->u + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1469                                            Data->iEdgedWidth/2);
1470                    sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1471                                            f_Ref->v + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1472                                            b_Ref->v + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1473                                            Data->iEdgedWidth/2);
1474    
1475                    if ((uint32_t) sum < MAX_CHROMA_SAD_FOR_SKIP * Data->iQuant) {
1476                            pMB->mode = MODE_DIRECT_NONE_MV;
1477                            return *Data->iMinSAD;
1478                    }
1479            }
1480    
1481            skip_sad = *Data->iMinSAD;
1482    
1483  //  DIRECT MODE DELTA VECTOR SEARCH.  //  DIRECT MODE DELTA VECTOR SEARCH.
1484  //      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
1485    
# Line 1123  Line 1487 
1487                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1488                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1489    
1490          (*MainSearchPtr)(0, 0, &Data, 255);          (*MainSearchPtr)(0, 0, Data, 255);
1491    
1492          HalfpelRefine(&Data);          HalfpelRefine(Data);
1493    
1494          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 * lambda_vec16[Data->iQuant]; // one bit is needed to code direct mode. we treat this bit just like it was vector's
1495          *best_sad = iMinSAD;          *best_sad = *Data->iMinSAD;
1496    
1497          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1498                  pMB->mode = MODE_DIRECT;                  pMB->mode = MODE_DIRECT;
1499          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1500    
1501          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1502    
1503          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1504                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1505                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = ((Data->currentMV->x == 0)
1506                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1507                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          : pMB->mvs[k].x - Data->referencemv[k].x);
1508                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1509                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1510                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1511                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1512                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1513                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1514                          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];
1515                          break;                          break;
1516                  }                  }
1517          }          }
1518          return 0;//skip_sad;          return skip_sad;
1519  }  }
1520    
1521    
1522  static __inline void  static __inline void
1523  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const uint8_t * const f_Ref,
1524                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
# Line 1168  Line 1533 
1533                                  const uint32_t fcode,                                  const uint32_t fcode,
1534                                  const uint32_t bcode,                                  const uint32_t bcode,
1535                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1536                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1537                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1538                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1539                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1540                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1541                                    SearchData * const fData)
1542    
1543  {  {
 /* 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". */  
1544    
1545          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1546    
1547          int iDirection, i, j;          int iDirection, i, j;
1548          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;  
   
1549    
1550          bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;          bData.iMinSAD = fData->iMinSAD;
1551          bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;          *bData.iMinSAD = 4096*256;
1552          bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;          bData.Cur = fData->Cur;
1553          bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;          fData->iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;
1554          bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;          bData.currentMV = fData->currentMV + 1;
1555          bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;          bData.iQuant = fData->iQuant;
1556          bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;          fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1557          bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;  
1558            bData.bRef = fData->Ref = f_Ref + (x + y * iEdgedWidth) * 16;
1559            bData.bRefH = fData->RefH = f_RefH + (x + y * iEdgedWidth) * 16;
1560            bData.bRefV = fData->RefV = f_RefV + (x + y * iEdgedWidth) * 16;
1561            bData.bRefHV = fData->RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;
1562            bData.Ref = fData->bRef = b_Ref + (x + y * iEdgedWidth) * 16;
1563            bData.RefH = fData->bRefH = b_RefH + (x + y * iEdgedWidth) * 16;
1564            bData.RefV = fData->bRefV = b_RefV + (x + y * iEdgedWidth) * 16;
1565            bData.RefHV = fData->bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;
1566    
1567            bData.bpredMV = fData->predMV = *f_predMV;
1568            fData->bpredMV = bData.predMV = *b_predMV;
1569    
1570            fData->currentMV[0] = pMB->mvs[0];
1571            fData->currentMV[1] = pMB->b_mvs[0];
1572            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);
1573            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);
1574    
1575            if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1576            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dy;
1577            if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dx;
1578            if (fData->currentMV[0].y > fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1579    
1580            if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1581            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dy;
1582            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dx;
1583            if (fData->currentMV[1].y > bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1584    
1585          bData.bpredMV = fData.predMV = *f_predMV;          CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
         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);  
1586    
1587  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)
1588    
1589          do {          do {
1590                  iDirection = 255;                  iDirection = 255;
1591                  // forward MV moves                  // forward MV moves
1592                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
1593    
1594                  CheckCandidateInt(i + 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1595                  CheckCandidateInt(i, j + 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1596                  CheckCandidateInt(i - 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1597                  CheckCandidateInt(i, j - 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
1598    
1599                  // backward MV moves                  // backward MV moves
1600                  i = currentMV[1].x; j = currentMV[1].y;                  i = fData->currentMV[1].x; j = fData->currentMV[1].y;
1601                  currentMV[2] = currentMV[0];                  fData->currentMV[2] = fData->currentMV[0];
1602    
1603                  CheckCandidateInt(i + 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1604                  CheckCandidateInt(i, j + 2, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1605                  CheckCandidateInt(i - 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
1606                  CheckCandidateInt(i, j - 2, 0, &iDirection, &bData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, &bData);
1607    
1608          } while (!(iDirection));          } while (!(iDirection));
1609    
 /* 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);  
         }  
   
1610  // 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
1611          iMinSAD +=  2 * lambda_vec16[iQuant];          *fData->iMinSAD +=  2 * lambda_vec16[fData->iQuant];
1612          if (iMinSAD < *best_sad) {          if (*fData->iMinSAD < *best_sad) {
1613                  *best_sad = iMinSAD;                  *best_sad = *fData->iMinSAD;
1614                  pMB->mvs[0] = currentMV[0];                  pMB->mvs[0] = fData->currentMV[0];
1615                  pMB->b_mvs[0] = currentMV[1];                  pMB->b_mvs[0] = fData->currentMV[1];
1616                  pMB->mode = MODE_INTERPOLATE;                  pMB->mode = MODE_INTERPOLATE;
1617    
1618                  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 1622 
1622          }          }
1623  }  }
1624    
1625    
1626  void  void
1627  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
1628                                           FRAMEINFO * const frame,                                           FRAMEINFO * const frame,
# Line 1293  Line 1651 
1651          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1652          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
1653    
1654    // some pre-inintialized data for the rest of the search
1655    
1656            SearchData Data;
1657            int32_t iMinSAD;
1658            VECTOR currentMV[3];
1659            Data.iEdgedWidth = pParam->edged_width;
1660            Data.currentMV = currentMV;
1661            Data.iMinSAD = &iMinSAD;
1662            Data.iQuant = frame->quant;
1663    
1664          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
1665    
1666          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
# Line 1309  Line 1677 
1677                                  continue;                                  continue;
1678                          }                          }
1679    
1680                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
1681  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
1682          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
1683    
1684                          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,
1685                                                                          b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,
1686                                                                          &frame->image,                                                                          &frame->image,
1687                                                                          i, j,                                                                          i, j,
1688                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
1689                                                                          TRB, TRD,                                                                          TRB, TRD,
1690                                                                          pParam,                                                                          pParam,
1691                                                                          pMB, b_mb,                                                                          pMB, b_mb,
1692                                                                          &best_sad);                                                                          &best_sad,
1693                                                                            &Data);
1694    
                         if (!(frame->global_flags & XVID_HALFPEL)) best_sad = skip_sad = 256*4096;  
                         else  
1695                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1696    
1697  //                      best_sad = 256*4096; //uncomment to disable Directsearch.  //                      best_sad = 256*4096; //uncomment to disable Directsearch.
# Line 1334  Line 1701 
1701                          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,
1702                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1703                                                  frame->motion_flags,                                                  frame->motion_flags,
1704                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
1705                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
1706                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
1707    
1708                          // backward search                          // backward search
1709                          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,
1710                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1711                                                  frame->motion_flags,                                                  frame->motion_flags,
1712                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
1713                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
1714                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
1715    
1716                          // 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
1717    
# Line 1354  Line 1721 
1721                                                  i, j,                                                  i, j,
1722                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
1723                                                  frame->motion_flags,                                                  frame->motion_flags,
1724                                                  frame->quant, pParam,                                                  pParam,
1725                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
1726                                                  pMB, &best_sad);                                                  pMB, &best_sad,
1727                                                    &Data);
1728    
1729                          switch (pMB->mode) {                          switch (pMB->mode) {
1730                                  case MODE_FORWARD:                                  case MODE_FORWARD:
# Line 1389  Line 1757 
1757    
1758  /* Hinted ME starts here */  /* Hinted ME starts here */
1759    
1760  static __inline void  static void
1761  Search8hinted(  const SearchData * const OldData,  Search8hinted(  const SearchData * const OldData,
1762                                  const int x, const int y,                                  const int x, const int y,
1763                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1764                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1765                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1766                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1767                                  const int block)                  const int block,
1768                    SearchData * const Data)
1769  {  {
1770          SearchData Data;          int32_t temp_sad;
1771          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1772            Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1773            Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1774            Data->iMinSAD = OldData->iMinSAD + 1 + block;
1775            Data->currentMV = OldData->currentMV + 1 + block;
1776            Data->currentQMV = OldData->currentQMV + 1 + block;
1777            Data->quarterpel = OldData->quarterpel;
1778    
1779            if (block != 0) {
1780                    if(pParam->m_quarterpel) {
1781                            *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *
1782                                                                            d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1783                                                                                                    Data->currentQMV->y - Data->predQMV.y,
1784                                                                                                    Data->iFcode);
1785                    }
1786                    else {
1787                            *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *
1788                                                                            d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1789                                                                                                    Data->currentMV->y - Data->predMV.y,
1790                                                                                                    Data->iFcode);
1791                    }
1792            }
1793    
1794          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));
1795          Data.iMinSAD = OldData->iMinSAD + 1 + block;          Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));
1796          Data.currentMV = OldData->currentMV+1+block;          Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1797          Data.iFcode = OldData->iFcode;          Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1798          Data.iQuant = OldData->iQuant;          Data->RefQ = OldData->RefQ;
   
         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));  
1799    
1800          CheckCandidate = CheckCandidate8;          Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
1801    
1802          if (block != 0)          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1803                  *(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);  
1804    
1805            CheckCandidate = CheckCandidate8;
1806    
1807          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); }  
1808    
1809          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1810                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1811                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1812    
1813          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1814    
1815            if(*(Data->iMinSAD) < temp_sad) {
1816                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1817                    Data->currentQMV->y = 2 * Data->currentMV->y;
1818            }
1819    
1820            if (MotionFlags & PMV_HALFPELREFINE8) {
1821                    temp_sad = *(Data->iMinSAD); // store current MinSAD
1822    
1823          if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                  HalfpelRefine(Data); // perform halfpel refine of current best vector
1824    
1825          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;                  if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1826          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;                          Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1827          pMB->mvs[block] = *(Data.currentMV);                          Data->currentQMV->y = 2 * Data->currentMV->y;
1828          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                  }
1829            }
1830    
1831            if((Data->quarterpel) && (!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1832               (MotionFlags & PMV_QUARTERPELREFINE8)) {
1833    
1834                    CheckCandidate = CheckCandidate8_qpel;
1835    
1836                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1837                                      pParam->width, pParam->height, OldData->iFcode, 0); // get real range
1838    
1839                    QuarterpelRefine(Data);
1840            }
1841    
1842            if(pParam->m_quarterpel) {
1843                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predQMV.x;
1844                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predQMV.y;
1845            }
1846            else {
1847                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1848                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1849            }
1850    
1851            pMB->mvs[block] = *(Data->currentMV);
1852            pMB->qmvs[block] = *(Data->currentQMV);
1853    
1854            pMB->sad8[block] =  4 * (*Data->iMinSAD);
1855  }  }
1856    
1857    
# Line 1450  Line 1860 
1860                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
1861                                  const uint8_t * const pRefV,                                  const uint8_t * const pRefV,
1862                                  const uint8_t * const pRefHV,                                  const uint8_t * const pRefHV,
1863                                    const uint8_t * const pRefQ,
1864                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1865                                  const int x,                                  const int x,
1866                                  const int y,                                  const int y,
1867                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1868                                  const uint32_t iQuant,                                  const uint32_t iQuant,
                                 const uint32_t iFcode,  
1869                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1870                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1871                                  int inter4v,                                  int inter4v,
1872                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
1873                                    SearchData * const Data)
1874  {  {
1875    
1876          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1877    
1878          int i;          int i, t;
         VECTOR currentMV[5];  
         int32_t iMinSAD[5];  
         int32_t temp[5];  
1879          MainSearchFunc * MainSearchPtr;          MainSearchFunc * MainSearchPtr;
         SearchData Data;  
1880    
1881          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1882          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1883                                  pParam->width, pParam->height, iFcode);          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1884                                    pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
1885    
1886            Data->Cur = pCur->y + (x + y * iEdgedWidth) * 16;
1887            Data->Ref = pRef + (x + iEdgedWidth*y)*16;
1888            Data->RefH = pRefH + (x + iEdgedWidth*y) * 16;
1889            Data->RefV = pRefV + (x + iEdgedWidth*y) * 16;
1890            Data->RefHV = pRefHV + (x + iEdgedWidth*y) * 16;
1891            Data->RefQ = pRefQ;
1892    
1893          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->iQuant = iQuant;
         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;  
         Data.iQuant = iQuant;  
         Data.iFcode = iFcode;  
1894    
1895          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
1896                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
1897                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
1898                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
1899                  Data.max_dy = EVEN(Data.max_dy);                  Data->max_dy = EVEN(Data->max_dy);
1900          }          }
1901    
1902          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;          for(i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
1903    
1904          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
1905    
# Line 1505  Line 1910 
1910    
1911          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);
1912          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);
1913          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
1914          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;
1915          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;
1916          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;
1917    
1918          CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);          (*CheckCandidate)(pMB->mvs[0].x, pMB->mvs[0].y, 0, &t, Data);
1919    
1920          if (pMB->mode == MODE_INTER4V)          if (pMB->mode == MODE_INTER4V)
1921                  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
1922                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);
1923                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);
1924                          if (!(make_mask(pMB->mvs, i)))                          if (!(make_mask(pMB->mvs, i)))
1925                                  CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);                                  (*CheckCandidate)(pMB->mvs[i].x, pMB->mvs[i].y, 0, &t, Data);
1926                  }                  }
1927    
1928          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1526  Line 1931 
1931                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1932                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1933    
1934          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1935    
1936            if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1937    
1938          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          for(i = 0; i < 5; i++) {
1939                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1940                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1941            }
1942    
1943            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1944          if (inter4v)          if (inter4v)
1945                  for(i = 0; i < 4; i++)                          CheckCandidate = CheckCandidate16_qpel;
1946                          Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                  else
1947                            CheckCandidate = CheckCandidate16no4v_qpel;
1948    
1949                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1950                                      pParam->width, pParam->height, Data->iFcode, 0); // get real range
1951    
1952                    QuarterpelRefine(Data);
1953            }
1954    
1955            if (inter4v) {
1956                    SearchData Data8;
1957                    Data8.iFcode = Data->iFcode;
1958                    Data8.iQuant = Data->iQuant;
1959                    Data8.iEdgedWidth = Data->iEdgedWidth;
1960                    Search8hinted(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1961                    Search8hinted(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1962                    Search8hinted(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1963                    Search8hinted(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1964            }
1965    
1966          if (!(inter4v) ||          if (!(inter4v) ||
1967                  (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] +
1968                                                            Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1969  // INTER MODE  // INTER MODE
1970    
1971                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1972                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1973                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1974    
1975                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1976                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1977    
1978                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1979                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1980          } else {          } else {
1981  // INTER4V MODE; all other things are already set in Search8hinted  // INTER4V MODE; all other things are already set in Search8hinted
1982                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1983                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3]
1984                                                    + Data->iMinSAD[4] + IMV16X16 * iQuant;
1985          }          }
1986    
1987  }  }
# Line 1568  Line 1999 
1999          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
2000    
2001          uint32_t x, y;          uint32_t x, y;
2002            uint8_t *qimage;
2003            int32_t temp[5], quant = current->quant;
2004            int32_t iMinSAD[5];
2005            VECTOR currentMV[5];
2006            VECTOR currentQMV[5];
2007            SearchData Data;
2008            Data.iEdgedWidth = pParam->edged_width;
2009            Data.currentMV = currentMV;
2010            Data.currentQMV = currentQMV;
2011            Data.iMinSAD = iMinSAD;
2012            Data.temp = temp;
2013            Data.iFcode = current->fcode;
2014            Data.rounding = pParam->m_rounding_type;
2015    
2016            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
2017                    return; // allocate some mem for qpel interpolated blocks
2018                                      // somehow this is dirty since I think we shouldn't use malloc outside
2019                                      // encoder_create() - so please fix me!
2020    
2021          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
2022    
2023          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
2024                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
                         int32_t sad00;  
2025    
2026                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2027    
2028  //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
2029                          if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;                          if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;
2030    
2031    
2032                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
2033                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
2034                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant; }
2035                            else
2036                                    if (pMB->dquant != NO_CHANGE) {
2037                                            quant += DQtab[pMB->dquant];
2038                                            if (quant > 31) quant = 31;
2039                                            else if (quant < 1) quant = 1;
2040                                            pMB->quant = quant;
2041                                    }
2042    
2043                          if (pMB->dquant == NO_CHANGE) //no skip otherwise, anyway                          SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, qimage, pCurrent, x,
2044                                  sad00 = pMB->sad16                                                          y, current->motion_flags, pMB->quant,
2045                                          = sad16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
2046                                                                  pRef->y + (x + y * pParam->edged_width) * 16,                                                          &Data);
                                                                 pParam->edged_width, 256*4096 );  
                         else sad00 = 256*4096;  
2047    
2048                    }
2049            }
2050            free(qimage);
2051    }
2052    
2053  //initial skip decision  static __inline int
2054    MEanalyzeMB (   const uint8_t * const pRef,
2055                                    const uint8_t * const pCur,
2056                                    const int x,
2057                                    const int y,
2058                                    const MBParam * const pParam,
2059                                    const MACROBLOCK * const pMBs,
2060                                    MACROBLOCK * const pMB,
2061                                    SearchData * const Data)
2062    {
2063    
2064                          if ( (pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)          int i, mask;
2065                                  && ( //(pMB->mode == MODE_NOT_CODED) ||          VECTOR pmv[3];
2066                                          (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant) )) ) {  
2067                                  if (sad00 < pMB->quant * INITIAL_SKIP_THRESH) {          *(Data->iMinSAD) = MV_MAX_ERROR;
2068                                          SkipMacroblockP(pMB, sad00);          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
2069                                          continue; } //skipped          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2070                                    pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
2071    
2072            Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
2073            Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
2074    
2075            CheckCandidate = CheckCandidate16no4vI;
2076    
2077            pmv[1].x = EVEN(pMB->mvs[0].x);
2078            pmv[1].y = EVEN(pMB->mvs[0].y);
2079            pmv[0].x = EVEN(Data->predMV.x);
2080            pmv[0].y = EVEN(Data->predMV.y);
2081            pmv[2].x = pmv[2].y = 0;
2082    
2083            CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, Data);
2084            if (!(mask = make_mask(pmv, 1)))
2085                    CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, Data);
2086            if (!(mask = make_mask(pmv, 2)))
2087                    CheckCandidate16no4vI(0, 0, mask, &i, Data);
2088    
2089            DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
2090    
2091            pMB->mvs[0] = pMB->mvs[1]
2092                            = pMB->mvs[2] = pMB->mvs[3] = *Data->currentMV; // all, for future get_pmv()
2093    
2094            return *(Data->iMinSAD);
2095                          }                          }
                         else sad00 = 256*4096;  
2096    
2097                          if (pMB->mode == MODE_NOT_CODED)  #define INTRA_THRESH    1350
2098                                  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);  
2099    
2100                          else  int
2101                                  SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,  MEanalysis(     const IMAGE * const pRef,
2102                                                          y, current->motion_flags, pMB->quant,                          const IMAGE * const pCurrent,
2103                                                          current->fcode, pParam, pMBs,                          MBParam * const pParam,
2104                                                          current->global_flags & XVID_INTER4V, pMB);                          MACROBLOCK * const pMBs,
2105                            const uint32_t iFcode)
2106    {
2107            uint32_t x, y, intra = 0;
2108            int sSAD = 0;
2109    
2110  /* final skip decision, a.k.a. "the vector you found, really that good?" */          VECTOR currentMV;
2111                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)          int32_t iMinSAD;
2112                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)          SearchData Data;
2113                                  SkipMacroblockP(pMB, sad00);          Data.iEdgedWidth = pParam->edged_width;
2114            Data.currentMV = &currentMV;
2115            Data.iMinSAD = &iMinSAD;
2116            Data.iFcode = iFcode;
2117            Data.iQuant = 2;
2118    
2119            if (sadInit) (*sadInit) ();
2120    
2121            for (y = 0; y < pParam->mb_height-1; y++) {
2122                    for (x = 0; x < pParam->mb_width; x++) {
2123                            int sad, dev;
2124                            MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2125    
2126                            sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
2127                                                                    pParam, pMBs, pMB, &Data);
2128    
2129                            if ( x != 0 && y != 0 && x != pParam->mb_width-1 ) { //no edge macroblocks, they just don't work
2130                                    if (sad > INTRA_THRESH) {
2131                                            dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
2132                                                                      pParam->edged_width);
2133                                            if (dev + INTRA_THRESH < sad) intra++;
2134                                            if (intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame
2135                                    }
2136                                    sSAD += sad;
2137                            }
2138    
2139                  }                  }
2140          }          }
2141            sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2142            if (sSAD > INTER_THRESH ) return 1; //P frame
2143            emms();
2144            return 0; // B frame
2145    
2146  }  }
2147    
2148    int
2149    FindFcode(      const MBParam * const pParam,
2150                            const FRAMEINFO * const current)
2151    {
2152            uint32_t x, y;
2153            int max = 0, min = 0, i;
2154    
2155            for (y = 0; y < pParam->mb_height; y++) {
2156                    for (x = 0; x < pParam->mb_width; x++) {
2157    
2158                            MACROBLOCK *pMB = &current->mbs[x + y * pParam->mb_width];
2159                            for(i = 0; i < (pMB->mode == MODE_INTER4V ? 4:1); i++) {
2160                                    if (pMB->mvs[i].x > max) max = pMB->mvs[i].x;
2161                                    if (pMB->mvs[i].y > max) max = pMB->mvs[i].y;
2162    
2163                                    if (pMB->mvs[i].x < min) min = pMB->mvs[i].x;
2164                                    if (pMB->mvs[i].y < min) min = pMB->mvs[i].y;
2165                            }
2166                    }
2167            }
2168    
2169            min = -min;
2170            max += 1;
2171            if (min > max) max = min;
2172    
2173            for (i = 1; (max > 32 << (i - 1)); i++);
2174            return i;
2175    }

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

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