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

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

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