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

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

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

revision 530, Mon Sep 23 20:36:02 2002 UTC revision 576, Thu Oct 3 08:26:19 2002 UTC
# Line 40  Line 40 
40  #include "motion_est.h"  #include "motion_est.h"
41  #include "motion.h"  #include "motion.h"
42  #include "sad.h"  #include "sad.h"
43    #include "../utils/emms.h"
44    
45  #define INITIAL_SKIP_THRESH     (10)  #define INITIAL_SKIP_THRESH     (10)
46  #define FINAL_SKIP_THRESH       (50)  #define FINAL_SKIP_THRESH       (50)
47  #define MAX_SAD00_FOR_SKIP      (20)  #define MAX_SAD00_FOR_SKIP      (20)
48  #define MAX_CHROMA_SAD_FOR_SKIP (18)  #define MAX_CHROMA_SAD_FOR_SKIP (22)
49  #define SKIP_THRESH_B (10)  #define SKIP_THRESH_B (25)
50    
51  #define CHECK_CANDIDATE(X,Y,D) { \  #define CHECK_CANDIDATE(X,Y,D) { \
52  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }
53    
54  #define iDiamondSize 2  #define iDiamondSize 2
55    
 //FILE * debug;  
   
56  static __inline int  static __inline int
57  d_mv_bits(int x, int y, const uint32_t iFcode)  d_mv_bits(int x, int y, const uint32_t iFcode)
58  {  {
# Line 79  Line 78 
78          return xb + yb;          return xb + yb;
79  }  }
80    
81  /* CHACK_CANDIATE FUNCTIONS START */  
82    /* CHECK_CANDIATE FUNCTIONS START */
83    
84  static void  static void
85  CheckCandidate16(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidate16(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
86  {  {
87          int32_t * const sad = data->temp;          int32_t * const sad = data->temp;
 //      static int32_t sad[5];  
88          int t;          int t;
89          const uint8_t * Reference;          const uint8_t * Reference;
90    
# Line 149  Line 148 
148  }  }
149    
150  static void  static void
151    CheckCandidate16no4vI(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
152    {
153            int32_t sad;
154    
155            if (( x > data->max_dx) || ( x < data->min_dx)
156                    || ( y > data->max_dy) || (y < data->min_dy)) return;
157    
158            sad = lambda_vec16[data->iQuant] *
159                            d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
160    
161            sad += sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),
162                                            data->iEdgedWidth, 256*4096);
163    
164            if (sad < *(data->iMinSAD)) {
165                    *(data->iMinSAD) = sad;
166                    data->currentMV[0].x = x; data->currentMV[0].y = y;
167                    *dir = Direction; }
168    }
169    
170    
171    static void
172  CheckCandidateInt(const int xf, const int yf, const int Direction, int * const dir, const SearchData * const data)  CheckCandidateInt(const int xf, const int yf, const int Direction, int * const dir, const SearchData * const data)
173  {  {
174          int32_t sad;          int32_t sad;
# Line 249  Line 269 
269          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
270          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
271    
272          if (( x > 31) || ( x < -31) || ( y > 31) || (y < -31)) return;          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
273    
274                  sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);                  sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);
275    
# Line 316  Line 336 
336                  *dir = Direction; }                  *dir = Direction; }
337  }  }
338    
339  /* CHACK_CANDIATE FUNCTIONS END */  /* CHECK_CANDIATE FUNCTIONS END */
340    
341  /* MAINSEARCH FUNCTIONS START */  /* MAINSEARCH FUNCTIONS START */
342    
# Line 497  Line 517 
517          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,
518                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);
519          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
520          sadC += sad8(current->v + x*8 + y*(iEdgedWidth/2)*8,          sadC += sad8(current->v + (x + y*(iEdgedWidth/2))*8,
521                                          reference->v + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                          reference->v + (x + y*(iEdgedWidth/2))*8, iEdgedWidth/2);
522          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
523    
524          return 1;          return 1;
# Line 508  Line 528 
528  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)
529  {  {
530          pMB->mode = MODE_NOT_CODED;          pMB->mode = MODE_NOT_CODED;
531          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = pMB->mv16.x = 0;          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;
532          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = pMB->mv16.y = 0;          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;
533          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;
534  }  }
535    
# Line 530  Line 550 
550    
551          uint32_t x, y;          uint32_t x, y;
552          uint32_t iIntra = 0;          uint32_t iIntra = 0;
553          int32_t InterBias;          int32_t InterBias, quant = current->quant;
554    
555            // some pre-initialized thingies for SearchP
556            int32_t temp[5];
557            VECTOR currentMV[5];
558            int32_t iMinSAD[5];
559            SearchData Data;
560            Data.iEdgedWidth = pParam->edged_width;
561            Data.currentMV = currentMV;
562            Data.iMinSAD = iMinSAD;
563            Data.temp = temp;
564            Data.iFcode = current->fcode;
565    
566          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
567    
# Line 546  Line 577 
577                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
578                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
579                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant; }
580                            else
581                                    if (pMB->dquant != NO_CHANGE) {
582                                            quant += DQtab[pMB->dquant];
583                                            if (quant > 31) quant = 31;
584                                            else if (quant < 1) quant = 1;
585                                            pMB->quant = quant;
586                                    }
587    
588  //initial skip decision  //initial skip decision
589    
# Line 559  Line 597 
597    
598                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
599                                                  y, current->motion_flags, pMB->quant,                                                  y, current->motion_flags, pMB->quant,
600                                                  current->fcode, pParam, pMBs, reference->mbs,                                                  &Data, pParam, pMBs, reference->mbs,
601                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
602    
603  /* final skip decision, a.k.a. "the vector you found, really that good?" */  /* final skip decision, a.k.a. "the vector you found, really that good?" */
# Line 584  Line 622 
622                                  if (deviation < (pMB->sad16 - InterBias)) {                                  if (deviation < (pMB->sad16 - InterBias)) {
623                                          if (++iIntra >= iLimit) return 1;                                          if (++iIntra >= iLimit) return 1;
624                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
625                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
626                                                  pMB->mvs[3] = zeroMV;                                                  pMB->mvs[3] = zeroMV;
627                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
628                                                  pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
# Line 601  Line 639 
639  static __inline int  static __inline int
640  make_mask(const VECTOR * const pmv, const int i)  make_mask(const VECTOR * const pmv, const int i)
641  {  {
642          int mask = 0xFF, j;          int mask = 255, j;
643          for (j = 0; j < i; j++) {          for (j = 0; j < i; j++) {
644                  if (MVequal(pmv[i], pmv[j])) return 0; // same vector has been checked already                  if (MVequal(pmv[i], pmv[j])) return 0; // same vector has been checked already
645                  if (pmv[i].x == pmv[j].x) {                  if (pmv[i].x == pmv[j].x) {
# Line 625  Line 663 
663    
664          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour
665                  pmv[5].x = EVEN(pmv[3].x);                  pmv[5].x = EVEN(pmv[3].x);
666                  pmv[5].y = EVEN(pmv[3].y); }                  pmv[5].y = EVEN(pmv[3].y);
667          else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
668    
669          if (x != 0) { pmv[3].x = EVEN(pmv[1].x); pmv[3].y = EVEN(pmv[1].y); }// pmv[3] is left neighbour          if (x != 0) { pmv[3].x = EVEN(pmv[1].x); pmv[3].y = EVEN(pmv[1].y); }// pmv[3] is left neighbour
670          else pmv[3].x = pmv[3].y = 0;          else pmv[3].x = pmv[3].y = 0;
# Line 644  Line 682 
682    
683          if ((x != iWcount-1) && (y != iHcount-1)) {          if ((x != iWcount-1) && (y != iHcount-1)) {
684                  pmv[6].x = EVEN((prevMB+1+iWcount)->mvs[0].x); //[6] right-down neighbour in last frame                  pmv[6].x = EVEN((prevMB+1+iWcount)->mvs[0].x); //[6] right-down neighbour in last frame
685                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y); }                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
686          else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
687  }  }
688    
689  static void  static void
# Line 658  Line 696 
696                  const int y,                  const int y,
697                  const uint32_t MotionFlags,                  const uint32_t MotionFlags,
698                  const uint32_t iQuant,                  const uint32_t iQuant,
699                  const uint32_t iFcode,                  SearchData * const Data,
700                  const MBParam * const pParam,                  const MBParam * const pParam,
701                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
702                  const MACROBLOCK * const prevMBs,                  const MACROBLOCK * const prevMBs,
# Line 666  Line 704 
704                  MACROBLOCK * const pMB)                  MACROBLOCK * const pMB)
705  {  {
706    
         const int32_t iEdgedWidth = pParam->edged_width;  
   
707          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
708          int32_t temp[5];          VECTOR pmv[7];
         VECTOR currentMV[5], pmv[7];  
         int32_t psad[4], iMinSAD[5];  
         MainSearchFunc * MainSearchPtr;  
         SearchData Data;  
   
         get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, psad);  //has to be changed to get_pmv(2)()  
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,  
                                 pParam->width, pParam->height, iFcode);  
709    
710          Data.predMV = pmv[0];          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()
711          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
712          Data.iEdgedWidth = iEdgedWidth;                                  pParam->width, pParam->height, Data->iFcode);
713          Data.currentMV = currentMV;  
714          Data.iMinSAD = iMinSAD;          Data->predMV = pmv[0];
715          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
716          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;
717          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
718          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
719          Data.temp = temp;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
720    
721          Data.iQuant = iQuant;          Data->iQuant = iQuant;
         Data.iFcode = iFcode;  
722    
723          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
724                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
725                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
726                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
727                  Data.max_dy = EVEN(Data.max_dy); }                  Data->max_dy = EVEN(Data->max_dy); }
   
         for(i = 0;  i < 5; i++) currentMV[i].x = currentMV[i].y = 0;  
   
         i = d_mv_bits(pmv[0].x, pmv[0].y, iFcode);  
   
         iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;  
         iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;  
         iMinSAD[2] = pMB->sad8[1];  
         iMinSAD[3] = pMB->sad8[2];  
         iMinSAD[4] = pMB->sad8[3];  
728    
729          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
730    
731            if (inter4v) CheckCandidate = CheckCandidate16;
732            else CheckCandidate = CheckCandidate16no4v;
733    
734            for(i = 0;  i < 5; i++) Data->currentMV[i].x = Data->currentMV[i].y = 0;
735    
736            i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);
737            Data->iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;
738            Data->iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;
739            Data->iMinSAD[2] = pMB->sad8[1];
740            Data->iMinSAD[3] = pMB->sad8[2];
741            Data->iMinSAD[4] = pMB->sad8[3];
742    
743          if ((x == 0) && (y == 0)) threshA = 512;          if ((x == 0) && (y == 0)) threshA = 512;
744          else {          else {
745                  threshA = psad[0] + 20;                  threshA = Data->temp[0]; // that's when we keep this SAD atm
746                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
747                  if (threshA > 1024) threshA = 1024; }                  if (threshA > 1024) threshA = 1024; }
748    
# Line 723  Line 752 
752          if (inter4v) CheckCandidate = CheckCandidate16;          if (inter4v) CheckCandidate = CheckCandidate16;
753          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
754    
755    
756  /* main loop. checking all predictions */  /* main loop. checking all predictions */
757    
758          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
759                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
760                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  (*CheckCandidate)(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
761                  if (iMinSAD[0] < threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
762          }          }
763    
764          if ((iMinSAD[0] <= threshA) ||          if ((Data->iMinSAD[0] <= threshA) ||
765                          (MVequal(currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
766                          (iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {                          (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {
767                  inter4v = 0;                  inter4v = 0;
768                  if (MotionFlags & PMV_QUICKSTOP16) goto PMVfast16_Terminate_without_Refine;          } else {
                 if (MotionFlags & PMV_EARLYSTOP16) {  
                         CheckCandidate = CheckCandidate16no4v; // I sure hope it's faster  
                         goto PMVfast16_Terminate_with_Refine;  
                 }  
         }  
769    
770          if (MotionFlags & PMV_USESQUARES16)                  MainSearchFunc * MainSearchPtr;
771                  MainSearchPtr = SquareSearch;                  if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
772          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
                 MainSearchPtr = AdvDiamondSearch;  
773                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
774    
775          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, iDirection);                  (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
776    
777  /* extended search, diamond starting in 0,0 and in prediction.  /* extended search, diamond starting in 0,0 and in prediction.
778          note that this search is/might be done in halfpel positions,          note that this search is/might be done in halfpel positions,
# Line 756  Line 780 
780    
781          if (MotionFlags & PMV_EXTSEARCH16) {          if (MotionFlags & PMV_EXTSEARCH16) {
782                  int32_t bSAD;                  int32_t bSAD;
783                  VECTOR startMV = Data.predMV, backupMV = currentMV[0];                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
784                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?
785                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);
786                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
787                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
788    
789                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, Data);
790                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
791                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
792                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
793                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
794                  }                  }
795    
796                  backupMV = currentMV[0];                          backupMV = Data->currentMV[0];
797                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;
798                  else startMV.x = startMV.y = 0;                  else startMV.x = startMV.y = 0;
799                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
800                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
801    
802                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, Data);
803                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
804                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
805                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
806                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
807                            }
808                  }                  }
809          }          }
810    
811  PMVfast16_Terminate_with_Refine:          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
   
         if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);  
   
 PMVfast16_Terminate_without_Refine:  
812    
813          if (inter4v)          if (inter4v) {
814                  for(i = 0; i < 4; i++)                  SearchData Data8;
815                          Search8(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                  Data8.iFcode = Data->iFcode;
816                    Data8.iQuant = Data->iQuant;
817                    Data8.iEdgedWidth = Data->iEdgedWidth;
818                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
819                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
820                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
821                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
822            }
823    
824          if (!(inter4v) ||          if (!(inter4v) ||
825                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
826                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
827  // INTER MODE  // INTER MODE
828                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
829                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
830                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
831    
832                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
833                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
834    
835                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
836                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
837          } else {          } else {
838  // INTER4V MODE; all other things are already set in Search8  // INTER4V MODE; all other things are already set in Search8
839                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
840                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
841                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
842          }          }
843    
844  }  }
# Line 820  Line 850 
850                  const MBParam * const pParam,                  const MBParam * const pParam,
851                  MACROBLOCK * const pMB,                  MACROBLOCK * const pMB,
852                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
853                  const int block)                  const int block,
854                    SearchData * const Data)
855  {  {
856          SearchData Data;          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
857            Data->iMinSAD = OldData->iMinSAD + 1 + block;
858          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          Data->currentMV = OldData->currentMV + 1 + block;
         Data.iMinSAD = OldData->iMinSAD + 1 + block;  
         Data.currentMV = OldData->currentMV+1+block;  
         Data.iFcode = OldData->iFcode;  
         Data.iQuant = OldData->iQuant;  
859    
860          if (block != 0)          if (block != 0)
861                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *                  *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *
862                                                                  d_mv_bits(      Data.currentMV->x - Data.predMV.x,                                                                  d_mv_bits(      Data->currentMV->x - Data->predMV.x,
863                                                                                          Data.currentMV->y - Data.predMV.y,                                                                                          Data->currentMV->y - Data->predMV.y,
864                                                                                          Data.iFcode);                                                                                          Data->iFcode);
   
865    
866          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
867    
868                  Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));
869                  Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));
870                  Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));
871                  Data.RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));
872    
873                  Data.iEdgedWidth = pParam->edged_width;                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
874    
875                  Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                  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,  
876                                  pParam->width, pParam->height, OldData->iFcode);                                  pParam->width, pParam->height, OldData->iFcode);
877    
878                  CheckCandidate = CheckCandidate8;                  CheckCandidate = CheckCandidate8;
# Line 860  Line 884 
884                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
885                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
886    
887                          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);     }                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);    }
888    
889                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(Data);
890          }          }
891    
892          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;          pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
893          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
894          pMB->mvs[block] = *(Data.currentMV);          pMB->mvs[block] = *(Data->currentMV);
895          pMB->sad8[block] =  4 * (*(Data.iMinSAD));          pMB->sad8[block] =  4 * (*Data->iMinSAD);
896    
897  }  }
898    
899  /* B-frames code starts here */  /* B-frames code starts here */
# Line 896  Line 921 
921          pmv[2] = ChoosePred(pMB, mode_curr);          pmv[2] = ChoosePred(pMB, mode_curr);
922          pmv[2].x = EVEN(pmv[2].x); pmv[2].y = EVEN(pmv[2].y);          pmv[2].x = EVEN(pmv[2].x); pmv[2].y = EVEN(pmv[2].y);
923    
         pmv[3].x = pmv[3].y = 0;  
924          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour
925                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);
926                  pmv[3].x = EVEN(pmv[3].x); pmv[3].y = EVEN(pmv[3].y); }                  pmv[3].x = EVEN(pmv[3].x); pmv[3].y = EVEN(pmv[3].y);
927            } else pmv[3].x = pmv[3].y = 0;
928    
929          if (y != 0) {          if (y != 0) {
930                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);
# Line 929  Line 954 
954                          const IMAGE * const pCur,                          const IMAGE * const pCur,
955                          const int x, const int y,                          const int x, const int y,
956                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
957                          const uint32_t iFcode,                          const uint32_t iFcode,
958                          const MBParam * const pParam,                          const MBParam * const pParam,
959                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
960                          const VECTOR * const predMV,                          const VECTOR * const predMV,
961                          int32_t * const best_sad,                          int32_t * const best_sad,
962                          const int32_t mode_current)                          const int32_t mode_current,
963                            SearchData * const Data)
964  {  {
965    
966          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
967    
968          int i, iDirection, mask;          int i, iDirection, mask;
969          VECTOR currentMV, pmv[7];          VECTOR pmv[7];
970          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
971          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
972          SearchData Data;          Data->iFcode = iFcode;
973    
974          Data.iMinSAD = &iMinSAD;          Data->Ref = pRef + (x + y * iEdgedWidth) * 16;
975          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->RefH = pRefH + (x + y * iEdgedWidth) * 16;
976          Data.iEdgedWidth = iEdgedWidth;          Data->RefV = pRefV + (x + y * iEdgedWidth) * 16;
977          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;  
978    
979          Data.iQuant = iQuant;          Data->predMV = *predMV;
         Data.iFcode = iFcode;  
         Data.predMV = *predMV;  
980    
981          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,
982                                  pParam->width, pParam->height, iFcode);                                  pParam->width, pParam->height, iFcode);
983    
984          if (!(MotionFlags & PMV_HALFPEL16)) {          pmv[0] = Data->predMV;
985                  Data.min_dx = EVEN(Data.min_dx);          PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
                 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?  
   
986    
987          pmv[0] = Data.predMV;          Data->currentMV->x = Data->currentMV->y = 0;
         PreparePredictionsBF(pmv, x, y, pParam->mb_width,  
                                         pMB, mode_current);  
   
         currentMV.x = currentMV.y = 0;  
988    
989          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
990    
991  // main loop. checking all predictions  // main loop. checking all predictions
992          for (i = 0; i < 8; i++) {          for (i = 0; i < 8; i++) {
993                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
994                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
995          }          }
996    
997          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 990  Line 1000 
1000                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1001                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1002    
1003          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1004    
1005          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          HalfpelRefine(Data);
1006    
1007  // three bits are needed to code backward mode. four for forward  // three bits are needed to code backward mode. four for forward
1008  // we treat the bits just like they were vector's  // we treat the bits just like they were vector's
1009          if (mode_current == MODE_FORWARD) iMinSAD +=  4 * lambda_vec16[iQuant];          if (mode_current == MODE_FORWARD) *Data->iMinSAD +=  4 * lambda_vec16[Data->iQuant];
1010          else iMinSAD +=  3 * lambda_vec16[iQuant];          else *Data->iMinSAD +=  3 * lambda_vec16[Data->iQuant];
1011    
1012    
1013          if (iMinSAD < *best_sad) {          if (*Data->iMinSAD < *best_sad) {
1014                  *best_sad = iMinSAD;                  *best_sad = *Data->iMinSAD;
1015                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1016                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1017                  pMB->pmvs[0].y = currentMV.y - predMV->y;                  pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1018                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = *Data->currentMV;
1019                  else pMB->b_mvs[0] = currentMV;                  else pMB->b_mvs[0] = *Data->currentMV;
1020          }          }
1021    
1022  }  }
1023    
1024  static int32_t  static int32_t
1025  SearchDirect(const uint8_t * const f_Ref,  SearchDirect(const IMAGE * const f_Ref,
1026                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1027                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
1028                                  const uint8_t * const f_RefHV,                                  const uint8_t * const f_RefHV,
1029                                  const uint8_t * const b_Ref,                                  const IMAGE * const b_Ref,
1030                                  const uint8_t * const b_RefH,                                  const uint8_t * const b_RefH,
1031                                  const uint8_t * const b_RefV,                                  const uint8_t * const b_RefV,
1032                                  const uint8_t * const b_RefHV,                                  const uint8_t * const b_RefHV,
1033                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1034                                  const int x, const int y,                                  const int x, const int y,
1035                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1036                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1037                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1038                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1039                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1040                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1041                                    SearchData * const Data)
1042    
1043  {  {
1044          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
         int32_t iMinSAD = 0, skip_sad;  
1045          int k;          int k;
1046          VECTOR currentMV;  
1047          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
         SearchData Data;  
1048    
1049          Data.iMinSAD = &iMinSAD;          *Data->iMinSAD = 256*4096;
1050          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;  
1051    
1052          Data.Ref= f_Ref + (x + iEdgedWidth*y) * 16;          Data->Ref = f_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1053          Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;          Data->RefH = f_RefH + (x + Data->iEdgedWidth*y) * 16;
1054          Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;          Data->RefV = f_RefV + (x + Data->iEdgedWidth*y) * 16;
1055          Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = f_RefHV + (x + Data->iEdgedWidth*y) * 16;
1056          Data.bRef = b_Ref + (x + iEdgedWidth*y) * 16;          Data->bRef = b_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1057          Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;          Data->bRefH = b_RefH + (x + Data->iEdgedWidth*y) * 16;
1058          Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;          Data->bRefV = b_RefV + (x + Data->iEdgedWidth*y) * 16;
1059          Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;          Data->bRefHV = b_RefHV + (x + Data->iEdgedWidth*y) * 16;
1060  /*  
1061  //What we do here is a complicated version of CheckCandidateDirect(0,0);          Data->max_dx = 2 * pParam->width - 2 * (x) * 16;
1062  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;
1063            Data->min_dx = -(2 * 16 + 2 * (x) * 16);
1064  */          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);  
1065    
1066          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1067                  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);
1068                  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;
1069                  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);
1070                  pMB->b_mvs[k].y = Data.directmvB[k].y = ((TRB - TRD) * Data.referencemv[k].y) / TRD;                  pMB->b_mvs[k].y = Data->directmvB[k].y = ((TRB - TRD) * Data->referencemv[k].y) / TRD;
   
         if (( pMB->mvs[k].x > Data.max_dx ) || ( pMB->mvs[k].x < Data.min_dx )  
                         || ( pMB->mvs[k].y > Data.max_dy ) || ( pMB->mvs[k].y < Data.min_dy )  
                         || ( pMB->b_mvs[k].x > Data.max_dx ) || ( pMB->b_mvs[k].x < Data.min_dx )  
                         || ( pMB->b_mvs[k].y > Data.max_dy ) || ( pMB->b_mvs[k].y < Data.min_dy )) {  
 /*  
                 fprintf(debug, "\nERROR - out of range : vector %d,%d and %d,%d\n", pMB->mvs[k].x, pMB->mvs[k].y,pMB->b_mvs[k].x,pMB->b_mvs[k].y );  
                 fprintf(debug, " range is x: %d..%d y: %d..%d \n", Data.min_dx,Data.max_dx,Data.min_dy,Data.max_dy);  
                 fprintf(debug,"macroblock %d, %d \n", x, y);  
                 fprintf(debug, "direct MV is %d,%d \n", directmv[k].x, directmv[k].y);  
 */  
                 *best_sad = 256*4096; // in that case, we won't use direct mode  
                 pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"  
                 pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;  /* because backwards and interpol might rely on this */  
                 return 0; }  
1071    
1072                    if ( ( pMB->b_mvs[k].x > Data->max_dx ) || ( pMB->b_mvs[k].x < Data->min_dx )
1073                            || ( pMB->b_mvs[k].y > Data->max_dy ) || ( pMB->b_mvs[k].y < Data->min_dy )) {
1074    
1075                            *best_sad = 256*4096; // in that case, we won't use direct mode
1076                            pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
1077                            pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;
1078                            return 0;
1079                    }
1080          if (b_mb->mode != MODE_INTER4V) {          if (b_mb->mode != MODE_INTER4V) {
1081                  iMinSAD = sad16bi(Data.Cur,                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1082                                                  get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,                          pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];
1083                                                                  x, y, 16, &pMB->mvs[0], iEdgedWidth),                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1084                                                  get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
                                                                 x, y, 16, &pMB->b_mvs[0], iEdgedWidth), iEdgedWidth);  
   
                 Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];  
                 Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];  
1085                  break;                  break;
1086          }          }
         iMinSAD += sad8bi(Data.Cur + (k&1)*8 + (k>>1)* 8 * iEdgedWidth,  
                                                 get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,  
                                                                 (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->mvs[k], iEdgedWidth),  
                                                 get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,  
                                                                 (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->b_mvs[k], iEdgedWidth),  
                                                 iEdgedWidth);  
1087          }          }
1088    
 // skip decision  
         if (iMinSAD < (int32_t)iQuant * SKIP_THRESH_B) {  
                 pMB->mode = MODE_DIRECT_NONE_MV;  
                 return iMinSAD; }  
   
         skip_sad = iMinSAD;  
         iMinSAD += 2 * lambda_vec16[iQuant]; // 2 bits needed to code vector 0,0  
         currentMV.x = currentMV.y = 0;  
1089          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1090                  CheckCandidate = CheckCandidateDirect;                  CheckCandidate = CheckCandidateDirect;
1091          else CheckCandidate = CheckCandidateDirectno4v;          else CheckCandidate = CheckCandidateDirectno4v;
1092    
1093            (*CheckCandidate)(0, 0, 255, &k, Data);
1094    
1095    // skip decision
1096            if (*Data->iMinSAD - 2 * lambda_vec16[Data->iQuant] < (int32_t)Data->iQuant * SKIP_THRESH_B) {
1097                    //checking chroma. everything copied from MC
1098                    //this is not full chroma compensation, only it's fullpel approximation. should work though
1099                    int sum, dx, dy, b_dx, b_dy;
1100    
1101                    sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1102                    dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1103    
1104                    sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1105                    dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1106    
1107                    sum = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;
1108                    b_dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1109    
1110                    sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;
1111                    b_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1112    
1113                    sum = sad8bi(pCur->u + 8*x + 8*y*(Data->iEdgedWidth/2),
1114                                            f_Ref->u + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1115                                            b_Ref->u + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1116                                            Data->iEdgedWidth/2);
1117                    sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1118                                            f_Ref->v + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1119                                            b_Ref->v + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1120                                            Data->iEdgedWidth/2);
1121    
1122                    if ((uint32_t) sum < MAX_CHROMA_SAD_FOR_SKIP * Data->iQuant) {
1123                            pMB->mode = MODE_DIRECT_NONE_MV;
1124                            return *Data->iMinSAD;
1125                    }
1126            }
1127    
1128            skip_sad = *Data->iMinSAD;
1129    
1130  //  DIRECT MODE DELTA VECTOR SEARCH.  //  DIRECT MODE DELTA VECTOR SEARCH.
1131  //      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
1132    
# Line 1123  Line 1134 
1134                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1135                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1136    
1137          (*MainSearchPtr)(0, 0, &Data, 255);          (*MainSearchPtr)(0, 0, Data, 255);
1138    
1139          HalfpelRefine(&Data);          HalfpelRefine(Data);
1140    
1141          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
1142          *best_sad = iMinSAD;          *best_sad = *Data->iMinSAD;
1143    
1144          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1145                  pMB->mode = MODE_DIRECT;                  pMB->mode = MODE_DIRECT;
1146          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1147    
1148          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1149    
1150          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1151                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1152                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = ((Data->currentMV->x == 0)
1153                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1154                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          : pMB->mvs[k].x - Data->referencemv[k].x);
1155                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1156                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1157                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1158                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1159                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1160                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1161                          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];
1162                          break;                          break;
1163                  }                  }
1164          }          }
1165          return 0;//skip_sad;          return skip_sad;
1166  }  }
1167    
1168    
1169  static __inline void  static __inline void
1170  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const uint8_t * const f_Ref,
1171                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
# Line 1168  Line 1180 
1180                                  const uint32_t fcode,                                  const uint32_t fcode,
1181                                  const uint32_t bcode,                                  const uint32_t bcode,
1182                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1183                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1184                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1185                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1186                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1187                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1188                                    SearchData * const fData)
1189    
1190  {  {
 /* 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". */  
1191    
1192          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1193    
1194          int iDirection, i, j;          int iDirection, i, j;
1195          int32_t iMinSAD = 256*4096;          SearchData bData;
         VECTOR currentMV[3];  
         SearchData fData, bData;  
   
   
         fData.iMinSAD = bData.iMinSAD = &iMinSAD;  
   
         fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
         fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;  
         fData.currentMV = currentMV; bData.currentMV = currentMV + 1;  
         fData.iQuant = bData.iQuant = iQuant;  
         fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;  
   
   
         bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  
         bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;  
         bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;  
         bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;  
         bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;  
         bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;  
         bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;  
         bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;  
1196    
1197          bData.bpredMV = fData.predMV = *f_predMV;          bData.iMinSAD = fData->iMinSAD;
1198          fData.bpredMV = bData.predMV = *b_predMV;          *bData.iMinSAD = 4096*256;
1199            bData.Cur = fData->Cur;
1200            fData->iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;
1201          currentMV[0] = pMB->mvs[0];          bData.currentMV = fData->currentMV + 1;
1202          currentMV[1] = pMB->b_mvs[0];          bData.iQuant = fData->iQuant;
1203          get_range(&fData.min_dx, &fData.max_dx, &fData.min_dy, &fData.max_dy, x, y, 16, pParam->width, pParam->height, fcode);          fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1204    
1205            bData.bRef = fData->Ref = f_Ref + (x + y * iEdgedWidth) * 16;
1206            bData.bRefH = fData->RefH = f_RefH + (x + y * iEdgedWidth) * 16;
1207            bData.bRefV = fData->RefV = f_RefV + (x + y * iEdgedWidth) * 16;
1208            bData.bRefHV = fData->RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;
1209            bData.Ref = fData->bRef = b_Ref + (x + y * iEdgedWidth) * 16;
1210            bData.RefH = fData->bRefH = b_RefH + (x + y * iEdgedWidth) * 16;
1211            bData.RefV = fData->bRefV = b_RefV + (x + y * iEdgedWidth) * 16;
1212            bData.RefHV = fData->bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;
1213    
1214            bData.bpredMV = fData->predMV = *f_predMV;
1215            fData->bpredMV = bData.predMV = *b_predMV;
1216    
1217            fData->currentMV[0] = pMB->mvs[0];
1218            fData->currentMV[1] = pMB->b_mvs[0];
1219            get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode);
1220          get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode);          get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode);
1221    
1222          CheckCandidateInt(currentMV[0].x, currentMV[0].y, 255, &iDirection, &fData);          if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1223            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dy;
1224            if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dx;
1225            if (fData->currentMV[0].y > fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1226    
1227            if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1228            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dy;
1229            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dx;
1230            if (fData->currentMV[1].y > bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1231    
1232            CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
1233    
1234  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)
1235    
1236          do {          do {
1237                  iDirection = 255;                  iDirection = 255;
1238                  // forward MV moves                  // forward MV moves
1239                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
1240    
1241                  CheckCandidateInt(i + 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1242                  CheckCandidateInt(i, j + 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1243                  CheckCandidateInt(i - 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1244                  CheckCandidateInt(i, j - 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
1245    
1246                  // backward MV moves                  // backward MV moves
1247                  i = currentMV[1].x; j = currentMV[1].y;                  i = fData->currentMV[1].x; j = fData->currentMV[1].y;
1248                  currentMV[2] = currentMV[0];                  fData->currentMV[2] = fData->currentMV[0];
1249    
1250                  CheckCandidateInt(i + 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1251                  CheckCandidateInt(i, j + 2, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1252                  CheckCandidateInt(i - 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
1253                  CheckCandidateInt(i, j - 2, 0, &iDirection, &bData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, &bData);
1254    
1255          } while (!(iDirection));          } while (!(iDirection));
1256    
 /* halfpel refinement. luckly we can use normal halfpel function for it */  
   
         if (MotionFlags & PMV_HALFPELREFINE16) {  
                 CheckCandidate = CheckCandidateInt;  
                 HalfpelRefine(&fData);  
                 currentMV[2] = currentMV[0];  
                 HalfpelRefine(&bData);  
         }  
   
1257  // 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
1258          iMinSAD +=  2 * lambda_vec16[iQuant];          *fData->iMinSAD +=  2 * lambda_vec16[fData->iQuant];
1259          if (iMinSAD < *best_sad) {          if (*fData->iMinSAD < *best_sad) {
1260                  *best_sad = iMinSAD;                  *best_sad = *fData->iMinSAD;
1261                  pMB->mvs[0] = currentMV[0];                  pMB->mvs[0] = fData->currentMV[0];
1262                  pMB->b_mvs[0] = currentMV[1];                  pMB->b_mvs[0] = fData->currentMV[1];
1263                  pMB->mode = MODE_INTERPOLATE;                  pMB->mode = MODE_INTERPOLATE;
1264    
1265                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;
# Line 1265  Line 1269 
1269          }          }
1270  }  }
1271    
1272    
1273  void  void
1274  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
1275                                           FRAMEINFO * const frame,                                           FRAMEINFO * const frame,
# Line 1293  Line 1298 
1298          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1299          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
1300    
1301    // some pre-inintialized data for the rest of the search
1302    
1303            SearchData Data;
1304            int32_t iMinSAD;
1305            VECTOR currentMV[3];
1306            Data.iEdgedWidth = pParam->edged_width;
1307            Data.currentMV = currentMV;
1308            Data.iMinSAD = &iMinSAD;
1309            Data.iQuant = frame->quant;
1310    
1311          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
1312    
1313          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
# Line 1309  Line 1324 
1324                                  continue;                                  continue;
1325                          }                          }
1326    
1327                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
1328  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
1329          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
1330    
1331                          skip_sad = SearchDirect(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                          skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
1332                                                                          b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,
1333                                                                          &frame->image,                                                                          &frame->image,
1334                                                                          i, j,                                                                          i, j,
1335                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
1336                                                                          TRB, TRD,                                                                          TRB, TRD,
1337                                                                          pParam,                                                                          pParam,
1338                                                                          pMB, b_mb,                                                                          pMB, b_mb,
1339                                                                          &best_sad);                                                                          &best_sad,
1340                                                                            &Data);
1341    
                         if (!(frame->global_flags & XVID_HALFPEL)) best_sad = skip_sad = 256*4096;  
                         else  
1342                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1343    
1344  //                      best_sad = 256*4096; //uncomment to disable Directsearch.  //                      best_sad = 256*4096; //uncomment to disable Directsearch.
# Line 1334  Line 1348 
1348                          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,
1349                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1350                                                  frame->motion_flags,                                                  frame->motion_flags,
1351                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
1352                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
1353                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
1354    
1355                          // backward search                          // backward search
1356                          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,
1357                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1358                                                  frame->motion_flags,                                                  frame->motion_flags,
1359                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
1360                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
1361                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
1362    
1363                          // 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
1364    
# Line 1354  Line 1368 
1368                                                  i, j,                                                  i, j,
1369                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
1370                                                  frame->motion_flags,                                                  frame->motion_flags,
1371                                                  frame->quant, pParam,                                                  pParam,
1372                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
1373                                                  pMB, &best_sad);                                                  pMB, &best_sad,
1374                                                    &Data);
1375    
1376                          switch (pMB->mode) {                          switch (pMB->mode) {
1377                                  case MODE_FORWARD:                                  case MODE_FORWARD:
# Line 1455  Line 1470 
1470                                  const int y,                                  const int y,
1471                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1472                                  const uint32_t iQuant,                                  const uint32_t iQuant,
                                 const uint32_t iFcode,  
1473                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1474                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1475                                  int inter4v,                                  int inter4v,
1476                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
1477                                    SearchData * const Data)
1478  {  {
1479    
1480          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1481    
1482          int i;          int i, t;
         VECTOR currentMV[5];  
         int32_t iMinSAD[5];  
         int32_t temp[5];  
1483          MainSearchFunc * MainSearchPtr;          MainSearchFunc * MainSearchPtr;
         SearchData Data;  
   
         Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);  
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,  
                                 pParam->width, pParam->height, iFcode);  
1484    
1485          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1486          Data.iEdgedWidth = iEdgedWidth;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1487          Data.currentMV = currentMV;                                  pParam->width, pParam->height, Data->iFcode);
1488          Data.iMinSAD = iMinSAD;  
1489          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data->Cur = pCur->y + (x + y * iEdgedWidth) * 16;
1490          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->Ref = pRef + (x + iEdgedWidth*y)*16;
1491          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + iEdgedWidth*y) * 16;
1492          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + iEdgedWidth*y) * 16;
1493          Data.temp = temp;          Data->RefHV = pRefHV + (x + iEdgedWidth*y) * 16;
1494          Data.iQuant = iQuant;          Data->iQuant = iQuant;
         Data.iFcode = iFcode;  
1495    
1496          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
1497                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
1498                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
1499                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
1500                  Data.max_dy = EVEN(Data.max_dy);                  Data->max_dy = EVEN(Data->max_dy);
1501          }          }
1502    
1503          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;          for(i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
1504    
1505          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
1506    
# Line 1505  Line 1511 
1511    
1512          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);
1513          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);
1514          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
1515          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;
1516          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;
1517          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;
1518    
1519          CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);          (*CheckCandidate)(pMB->mvs[0].x, pMB->mvs[0].y, 0, &t, Data);
1520    
1521          if (pMB->mode == MODE_INTER4V)          if (pMB->mode == MODE_INTER4V)
1522                  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
1523                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);
1524                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);
1525                          if (!(make_mask(pMB->mvs, i)))                          if (!(make_mask(pMB->mvs, i)))
1526                                  CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);                                  (*CheckCandidate)(pMB->mvs[i].x, pMB->mvs[i].y, 0, &t, Data);
1527                  }                  }
1528    
1529          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1526  Line 1532 
1532                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1533                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1534    
1535          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1536    
1537          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1538    
1539          if (inter4v)          if (inter4v)
1540                  for(i = 0; i < 4; i++)                  for(i = 0; i < 4; i++)
1541                          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);
1542    
1543          if (!(inter4v) ||          if (!(inter4v) ||
1544                  (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] +
1545                                                            Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1546  // INTER MODE  // INTER MODE
1547    
1548                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1549                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1550                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1551    
1552                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1553                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1554    
1555                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1556                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1557          } else {          } else {
1558  // INTER4V MODE; all other things are already set in Search8hinted  // INTER4V MODE; all other things are already set in Search8hinted
1559                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1560                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3]
1561                                                    + Data->iMinSAD[4] + IMV16X16 * iQuant;
1562          }          }
1563    
1564  }  }
# Line 1568  Line 1576 
1576          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
1577    
1578          uint32_t x, y;          uint32_t x, y;
1579            int32_t temp[5], quant = current->quant;
1580            int32_t iMinSAD[5];
1581            VECTOR currentMV[5];
1582            SearchData Data;
1583            Data.iEdgedWidth = pParam->edged_width;
1584            Data.currentMV = currentMV;
1585            Data.iMinSAD = iMinSAD;
1586            Data.temp = temp;
1587            Data.iFcode = current->fcode;
1588    
1589          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
1590    
1591          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
1592                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
                         int32_t sad00;  
1593    
1594                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
1595    
1596  //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
1597                          if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;                          if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;
1598    
1599    
1600                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
1601                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
1602                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant; }
1603                            else
1604                                    if (pMB->dquant != NO_CHANGE) {
1605                                            quant += DQtab[pMB->dquant];
1606                                            if (quant > 31) quant = 31;
1607                                            else if (quant < 1) quant = 1;
1608                                            pMB->quant = quant;
1609                                    }
1610    
1611                          if (pMB->dquant == NO_CHANGE) //no skip otherwise, anyway                          SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
1612                                  sad00 = pMB->sad16                                                          y, current->motion_flags, pMB->quant,
1613                                          = sad16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
1614                                                                  pRef->y + (x + y * pParam->edged_width) * 16,                                                          &Data);
1615                                                                  pParam->edged_width, 256*4096 );  
1616                          else sad00 = 256*4096;                  }
1617            }
1618    }
1619    
1620    static __inline int
1621    MEanalyzeMB (   const uint8_t * const pRef,
1622                                    const uint8_t * const pCur,
1623                                    const int x,
1624                                    const int y,
1625                                    const MBParam * const pParam,
1626                                    const MACROBLOCK * const pMBs,
1627                                    MACROBLOCK * const pMB,
1628                                    SearchData * const Data)
1629    {
1630    
1631            int i, mask;
1632            VECTOR pmv[3];
1633    
1634  //initial skip decision          *(Data->iMinSAD) = MV_MAX_ERROR;
1635            Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1636            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1637                                    pParam->width, pParam->height, Data->iFcode);
1638    
1639                          if ( (pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)          Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
1640                                  && ( //(pMB->mode == MODE_NOT_CODED) ||          Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
1641                                          (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant) )) ) {  
1642                                  if (sad00 < pMB->quant * INITIAL_SKIP_THRESH) {          CheckCandidate = CheckCandidate16no4vI;
1643                                          SkipMacroblockP(pMB, sad00);  
1644                                          continue; } //skipped          pmv[1].x = EVEN(pMB->mvs[0].x);
1645            pmv[1].y = EVEN(pMB->mvs[0].y);
1646            pmv[0].x = EVEN(Data->predMV.x);
1647            pmv[0].y = EVEN(Data->predMV.y);
1648            pmv[2].x = pmv[2].y = 0;
1649    
1650            CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, Data);
1651            if (!(mask = make_mask(pmv, 1)))
1652                    CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, Data);
1653            if (!(mask = make_mask(pmv, 2)))
1654                    CheckCandidate16no4vI(0, 0, mask, &i, Data);
1655    
1656            DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
1657    
1658            pMB->mvs[0] = pMB->mvs[1]
1659                            = pMB->mvs[2] = pMB->mvs[3] = *Data->currentMV; // all, for future get_pmv()
1660    
1661            return *(Data->iMinSAD);
1662                          }                          }
                         else sad00 = 256*4096;  
1663    
1664                          if (pMB->mode == MODE_NOT_CODED)  #define INTRA_THRESH    1350
1665                                  SearchP(        pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,  #define INTER_THRESH    900
                                                         y, current->motion_flags, pMB->quant,  
                                                         current->fcode, pParam, pMBs, reference->mbs,  
                                                         current->global_flags & XVID_INTER4V, pMB);  
1666    
1667                          else  int
1668                                  SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,  MEanalysis(     const IMAGE * const pRef,
1669                                                          y, current->motion_flags, pMB->quant,                          const IMAGE * const pCurrent,
1670                                                          current->fcode, pParam, pMBs,                          MBParam * const pParam,
1671                                                          current->global_flags & XVID_INTER4V, pMB);                          MACROBLOCK * const pMBs,
1672                            const uint32_t iFcode)
1673    {
1674            uint32_t x, y, intra = 0;
1675            int sSAD = 0;
1676    
1677  /* final skip decision, a.k.a. "the vector you found, really that good?" */          VECTOR currentMV;
1678                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)          int32_t iMinSAD;
1679                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)          SearchData Data;
1680                                  SkipMacroblockP(pMB, sad00);          Data.iEdgedWidth = pParam->edged_width;
1681            Data.currentMV = &currentMV;
1682            Data.iMinSAD = &iMinSAD;
1683            Data.iFcode = iFcode;
1684            Data.iQuant = 2;
1685    
1686            if (sadInit) (*sadInit) ();
1687    
1688            for (y = 0; y < pParam->mb_height-1; y++) {
1689                    for (x = 0; x < pParam->mb_width; x++) {
1690                            int sad, dev;
1691                            MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
1692    
1693                            sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
1694                                                                    pParam, pMBs, pMB, &Data);
1695    
1696                            if ( x != 0 && y != 0 && x != pParam->mb_width-1 ) { //no edge macroblocks, they just don't work
1697                                    if (sad > INTRA_THRESH) {
1698                                            dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
1699                                                                      pParam->edged_width);
1700                                            if (dev + INTRA_THRESH < sad) intra++;
1701                                            if (intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame
1702                                    }
1703                                    sSAD += sad;
1704                            }
1705    
1706                  }                  }
1707          }          }
1708            sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
1709            if (sSAD > INTER_THRESH ) return 1; //P frame
1710            emms();
1711            return 0; // B frame
1712    
1713  }  }
1714    
1715    int
1716    FindFcode(      const MBParam * const pParam,
1717                            const FRAMEINFO * const current)
1718    {
1719            uint32_t x, y;
1720            int max = 0, min = 0, i;
1721    
1722            for (y = 0; y < pParam->mb_height; y++) {
1723                    for (x = 0; x < pParam->mb_width; x++) {
1724    
1725                            MACROBLOCK *pMB = &current->mbs[x + y * pParam->mb_width];
1726                            for(i = 0; i < (pMB->mode == MODE_INTER4V ? 4:1); i++) {
1727                                    if (pMB->mvs[i].x > max) max = pMB->mvs[i].x;
1728                                    if (pMB->mvs[i].y > max) max = pMB->mvs[i].y;
1729    
1730                                    if (pMB->mvs[i].x < min) min = pMB->mvs[i].x;
1731                                    if (pMB->mvs[i].y < min) min = pMB->mvs[i].y;
1732                            }
1733                    }
1734            }
1735    
1736            min = -min;
1737            max += 1;
1738            if (min > max) max = min;
1739    
1740            for (i = 1; (max > 32 << (i - 1)); i++);
1741            return i;
1742    }

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

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