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

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

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