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

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

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