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

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

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

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

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

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