[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 739, Tue Dec 24 16:44:24 2002 UTC revision 767, Wed Jan 8 14:37:52 2003 UTC
# Line 58  Line 58 
58          int xb, yb;          int xb, yb;
59          if (qpel) { x *= 2; y *= 2;}          if (qpel) { x *= 2; y *= 2;}
60          else if (rrv) { x = RRV_MV_SCALEDOWN(x); y = RRV_MV_SCALEDOWN(y); }          else if (rrv) { x = RRV_MV_SCALEDOWN(x); y = RRV_MV_SCALEDOWN(y); }
61          x = pred.x - x;          x -= pred.x;
62          y = pred.y - y;          y -= pred.y;
63    
64          if (x == 0) xb = 1;          if (x) {
         else {  
65                  if (x < 0) x = -x;                  if (x < 0) x = -x;
66                  x += (1 << (iFcode - 1)) - 1;                  x += (1 << (iFcode - 1)) - 1;
67                  x >>= (iFcode - 1);                  x >>= (iFcode - 1);
68                  if (x > 32) x = 32;                  if (x > 32) x = 32;
69                  xb = mvtab[x] + iFcode;                  xb = mvtab[x] + iFcode;
70          }          } else xb = 1;
71    
72          if (y == 0) yb = 1;          if (y) {
         else {  
73                  if (y < 0) y = -y;                  if (y < 0) y = -y;
74                  y += (1 << (iFcode - 1)) - 1;                  y += (1 << (iFcode - 1)) - 1;
75                  y >>= (iFcode - 1);                  y >>= (iFcode - 1);
76                  if (y > 32) y = 32;                  if (y > 32) y = 32;
77                  yb = mvtab[y] + iFcode;                  yb = mvtab[y] + iFcode;
78          }          } else yb = 1;
79          return xb + yb;          return xb + yb;
80  }  }
81    
# Line 85  Line 83 
83  ChromaSAD(int dx, int dy, const SearchData * const data)  ChromaSAD(int dx, int dy, const SearchData * const data)
84  {  {
85          int sad;          int sad;
86          dx = (dx >> 1) + roundtab_79[dx & 0x3];          const uint32_t stride = data->iEdgedWidth/2;
         dy = (dy >> 1) + roundtab_79[dy & 0x3];  
87    
88          if (dx == data->temp[5] && dy == data->temp[6]) return data->temp[7]; //it has been checked recently          if (dx == data->temp[5] && dy == data->temp[6]) return data->temp[7]; //it has been checked recently
89            data->temp[5]  = dx; data->temp[6] = dy; // backup
90    
91          switch (((dx & 1) << 1) | (dy & 1))     {          switch (((dx & 1) << 1) | (dy & 1))     {
92                  case 0:                  case 0:
93                          sad = sad8(data->CurU, data->RefCU + (dy/2) * (data->iEdgedWidth/2) + dx/2, data->iEdgedWidth/2);                          dx = dx / 2; dy = dy / 2;
94                          sad += sad8(data->CurV, data->RefCV + (dy/2) * (data->iEdgedWidth/2) + dx/2, data->iEdgedWidth/2);                          sad = sad8(data->CurU, data->RefCU + dy * stride + dx, stride);
95                            sad += sad8(data->CurV, data->RefCV + dy * stride + dx, stride);
96                          break;                          break;
97                  case 1:                  case 1:
98                          dx = dx / 2; dy = (dy - 1) / 2;                          dx = dx / 2; dy = (dy - 1) / 2;
99                          sad = sad8bi(data->CurU, data->RefCU + dy * (data->iEdgedWidth/2) + dx, data->RefCU + (dy+1) * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2);                          sad = sad8bi(data->CurU, data->RefCU + dy * stride + dx, data->RefCU + (dy+1) * stride + dx, stride);
100                          sad += sad8bi(data->CurV, data->RefCV + dy * (data->iEdgedWidth/2) + dx, data->RefCV + (dy+1) * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2);                          sad += sad8bi(data->CurV, data->RefCV + dy * stride + dx, data->RefCV + (dy+1) * stride + dx, stride);
101                          break;                          break;
102                  case 2:                  case 2:
103                          dx = (dx - 1) / 2; dy = dy / 2;                          dx = (dx - 1) / 2; dy = dy / 2;
104                          sad = sad8bi(data->CurU, data->RefCU + dy * (data->iEdgedWidth/2) + dx, data->RefCU + dy * (data->iEdgedWidth/2) + dx+1, data->iEdgedWidth/2);                          sad = sad8bi(data->CurU, data->RefCU + dy * stride + dx, data->RefCU + dy * stride + dx+1, stride);
105                          sad += sad8bi(data->CurV, data->RefCV + dy * (data->iEdgedWidth/2) + dx, data->RefCV + dy * (data->iEdgedWidth/2) + dx+1, data->iEdgedWidth/2);                          sad += sad8bi(data->CurV, data->RefCV + dy * stride + dx, data->RefCV + dy * stride + dx+1, stride);
106                          break;                          break;
107                  default:                  default:
108                          dx = (dx - 1) / 2; dy = (dy - 1) / 2;                          dx = (dx - 1) / 2; dy = (dy - 1) / 2;
109                          interpolate8x8_halfpel_hv(data->RefQ,                          interpolate8x8_halfpel_hv(data->RefQ, data->RefCU + dy * stride + dx, stride, data->rounding);
110                                                                           data->RefCU + dy * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2,                          sad = sad8(data->CurU, data->RefQ, stride);
111                                                                           data->rounding);  
112                          sad = sad8(data->CurU, data->RefQ, data->iEdgedWidth/2);                          interpolate8x8_halfpel_hv(data->RefQ, data->RefCV + dy * stride + dx, stride, data->rounding);
113                          interpolate8x8_halfpel_hv(data->RefQ,                          sad += sad8(data->CurV, data->RefQ, stride);
                                                                          data->RefCV + dy * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2,  
                                                                          data->rounding);  
                         sad += sad8(data->CurV, data->RefQ, data->iEdgedWidth/2);  
114                          break;                          break;
115          }          }
116          data->temp[5]  = dx; data->temp[6] = dy; data->temp[7] = sad; //backup          data->temp[7] = sad; //backup, part 2
117          return sad;          return sad;
118  }  }
119    
120  static __inline const uint8_t *  static __inline const uint8_t *
121  GetReference(const int x, const int y, const int dir, const SearchData * const data)  GetReferenceB(const int x, const int y, const int dir, const SearchData * const data)
122  {  {
123  //      dir : 0 = forward, 1 = backward  //      dir : 0 = forward, 1 = backward
124          switch ( (dir << 2) | ((x&1)<<1) | (y&1) ) {          switch ( (dir << 2) | ((x&1)<<1) | (y&1) ) {
# Line 137  Line 133 
133          }          }
134  }  }
135    
136    // this is a simpler copy of GetReferenceB, but as it's __inline anyway, we can keep the two separate
137    static __inline const uint8_t *
138    GetReference(const int x, const int y, const SearchData * const data)
139    {
140            switch ( ((x&1)<<1) | (y&1) ) {
141                    case 0 : return data->Ref + x/2 + (y/2)*(data->iEdgedWidth);
142                    case 1 : return data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth);
143                    case 2 : return data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth);
144                    default : return data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth);
145            }
146    }
147    
148  static uint8_t *  static uint8_t *
149  Interpolate8x8qpel(const int x, const int y, const int block, const int dir, const SearchData * const data)  Interpolate8x8qpel(const int x, const int y, const int block, const int dir, const SearchData * const data)
150  {  {
# Line 148  Line 156 
156          const int halfpel_y = y/2;          const int halfpel_y = y/2;
157          const uint8_t *ref1, *ref2, *ref3, *ref4;          const uint8_t *ref1, *ref2, *ref3, *ref4;
158    
159          ref1 = GetReference(halfpel_x, halfpel_y, dir, data); // this reference is used in all cases          ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
160          ref1 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;          ref1 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
161          switch( ((x&1)<<1) + (y&1) ) {          switch( ((x&1)<<1) + (y&1) ) {
162          case 0: // pure halfpel position          case 0: // pure halfpel position
163                  Reference = (uint8_t *) GetReference(halfpel_x, halfpel_y, dir, data);                  return (uint8_t *) ref1;
                 Reference += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;  
164                  break;                  break;
165    
166          case 1: // x halfpel, y qpel - top or bottom during qpel refinement          case 1: // x halfpel, y qpel - top or bottom during qpel refinement
167                  ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);                  ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
168                  ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;                  ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
169                  interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);                  interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
170                  break;                  break;
171    
172          case 2: // x qpel, y halfpel - left or right during qpel refinement          case 2: // x qpel, y halfpel - left or right during qpel refinement
173                  ref2 = GetReference(x - halfpel_x, halfpel_y, dir, data);                  ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
174                  ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;                  ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
175                  interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);                  interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
176                  break;                  break;
177    
178          default: // x and y in qpel resolution - the "corners" (top left/right and          default: // x and y in qpel resolution - the "corners" (top left/right and
179                           // bottom left/right) during qpel refinement                           // bottom left/right) during qpel refinement
180                  ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);                  ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
181                  ref3 = GetReference(x - halfpel_x, halfpel_y, dir, data);                  ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
182                  ref4 = GetReference(x - halfpel_x, y - halfpel_y, dir, data);                  ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
183                  ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;                  ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
184                  ref3 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;                  ref3 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
185                  ref4 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;                  ref4 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
# Line 193  Line 200 
200          const int halfpel_y = y/2;          const int halfpel_y = y/2;
201          const uint8_t *ref1, *ref2, *ref3, *ref4;          const uint8_t *ref1, *ref2, *ref3, *ref4;
202    
203          ref1 = GetReference(halfpel_x, halfpel_y, dir, data); // this reference is used in all cases          ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
204          switch( ((x&1)<<1) + (y&1) ) {          switch( ((x&1)<<1) + (y&1) ) {
205          case 0: // pure halfpel position          case 0: // pure halfpel position
206                  return (uint8_t *) GetReference(halfpel_x, halfpel_y, dir, data);                  return (uint8_t *) ref1;
207          case 1: // x halfpel, y qpel - top or bottom during qpel refinement          case 1: // x halfpel, y qpel - top or bottom during qpel refinement
208                  ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);                  ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
209                  interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);                  interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
210                  interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);                  interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
211                  interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);                  interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
# Line 206  Line 213 
213                  break;                  break;
214    
215          case 2: // x qpel, y halfpel - left or right during qpel refinement          case 2: // x qpel, y halfpel - left or right during qpel refinement
216                  ref2 = GetReference(x - halfpel_x, halfpel_y, dir, data);                  ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
217                  interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);                  interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
218                  interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);                  interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
219                  interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);                  interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
# Line 215  Line 222 
222    
223          default: // x and y in qpel resolution - the "corners" (top left/right and          default: // x and y in qpel resolution - the "corners" (top left/right and
224                           // bottom left/right) during qpel refinement                           // bottom left/right) during qpel refinement
225                  ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);                  ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
226                  ref3 = GetReference(x - halfpel_x, halfpel_y, dir, data);                  ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
227                  ref4 = GetReference(x - halfpel_x, y - halfpel_y, dir, data);                  ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
228                  interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);                  interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
229                  interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);                  interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
230                  interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);                  interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
# Line 244  Line 251 
251                  xc = x/2; yc = y/2; //for chroma sad                  xc = x/2; yc = y/2; //for chroma sad
252                  current = data->currentQMV;                  current = data->currentQMV;
253          } else {          } else {
254                  Reference = GetReference(x, y, 0, data);                  Reference = GetReference(x, y, data);
255                  current = data->currentMV;                  current = data->currentMV;
256                  xc = x; yc = y;                  xc = x; yc = y;
257          }          }
# Line 255  Line 262 
262          data->temp[0] += (data->lambda16 * t * data->temp[0])/1000;          data->temp[0] += (data->lambda16 * t * data->temp[0])/1000;
263          data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))/100;          data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))/100;
264    
265          if (data->chroma) data->temp[0] += ChromaSAD(xc, yc, data);          if (data->chroma) data->temp[0] += ChromaSAD((xc >> 1) + roundtab_79[xc & 0x3],
266                                                                                                            (yc >> 1) + roundtab_79[yc & 0x3], data);
267    
268          if (data->temp[0] < data->iMinSAD[0]) {          if (data->temp[0] < data->iMinSAD[0]) {
269                  data->iMinSAD[0] = data->temp[0];                  data->iMinSAD[0] = data->temp[0];
# Line 283  Line 291 
291                  ( x > data->max_dx) || ( x < data->min_dx)                  ( x > data->max_dx) || ( x < data->min_dx)
292                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
293    
294          Reference = GetReference(x, y, 0, data);          Reference = GetReference(x, y, data);
295          t = d_mv_bits(x, y, data->predMV, data->iFcode, 0, 1);          t = d_mv_bits(x, y, data->predMV, data->iFcode, 0, 1);
296    
297          data->temp[0] = sad32v_c(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);          data->temp[0] = sad32v_c(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
# Line 324  Line 332 
332                  Reference = Interpolate16x16qpel(x, y, 0, data);                  Reference = Interpolate16x16qpel(x, y, 0, data);
333                  current = data->currentQMV;                  current = data->currentQMV;
334          } else {          } else {
335                  Reference = GetReference(x, y, 0, data);                  Reference = GetReference(x, y, data);
336                  current = data->currentMV;                  current = data->currentMV;
337          }          }
338          t = d_mv_bits(x, y, data->predMV, data->iFcode,          t = d_mv_bits(x, y, data->predMV, data->iFcode,
339                                          data->qpel && !data->qpel_precision && !data->rrv, data->rrv);                                          data->qpel && !data->qpel_precision, data->rrv);
340    
341          sad = sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);          sad = sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);
342          sad += (data->lambda16 * t * sad)/1000;          sad += (data->lambda16 * t * sad)/1000;
# Line 364  Line 372 
372    
373  }  }
374    
   
375  static void  static void
376  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)
377  {  {
# Line 382  Line 389 
389                  current = data->currentQMV;                  current = data->currentQMV;
390                  ReferenceB = Interpolate16x16qpel(xb, yb, 1, data);                  ReferenceB = Interpolate16x16qpel(xb, yb, 1, data);
391          } else {          } else {
392                  ReferenceF = GetReference(xf, yf, 0, data);                  ReferenceF = GetReference(xf, yf, data);
393                  xb = data->currentMV[1].x; yb = data->currentMV[1].y;                  xb = data->currentMV[1].x; yb = data->currentMV[1].y;
394                  ReferenceB = GetReference(xb, yb, 1, data);                  ReferenceB = GetReferenceB(xb, yb, 1, data);
395                  current = data->currentMV;                  current = data->currentMV;
396          }          }
397    
# Line 501  Line 508 
508                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
509    
510          if (data->qpel) Reference = Interpolate16x16qpel(x, y, 0, data);          if (data->qpel) Reference = Interpolate16x16qpel(x, y, 0, data);
511          else Reference =  GetReference(x, y, 0, data);          else Reference =  GetReference(x, y, data);
512    
513          sad = sad8(data->Cur, Reference, data->iEdgedWidth);          sad = sad8(data->Cur, Reference, data->iEdgedWidth);
514          t = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel && !data->qpel_precision, 0);          t = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel && !data->qpel_precision, 0);
# Line 674  Line 681 
681                  backupMV = *(data->currentQMV);                  backupMV = *(data->currentQMV);
682          else backupMV = *(data->currentMV);          else backupMV = *(data->currentMV);
683    
684          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);          CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);
685          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);
         CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);  
         CHECK_CANDIDATE(backupMV.x + 1, backupMV.y + 1, 0);  
   
         CHECK_CANDIDATE(backupMV.x - 1, backupMV.y, 0);  
686          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y, 0);          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y, 0);
687            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y + 1, 0);
688          CHECK_CANDIDATE(backupMV.x, backupMV.y + 1, 0);          CHECK_CANDIDATE(backupMV.x, backupMV.y + 1, 0);
689          CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);
690            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y, 0);
691            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);
692  }  }
693    
694  static __inline int  static __inline int
# Line 748  Line 753 
753          uint32_t x, y;          uint32_t x, y;
754          uint32_t iIntra = 0;          uint32_t iIntra = 0;
755          int32_t InterBias, quant = current->quant, sad00;          int32_t InterBias, quant = current->quant, sad00;
         uint8_t *qimage;  
756    
757          // some pre-initialized thingies for SearchP          // some pre-initialized thingies for SearchP
758          int32_t temp[8];          int32_t temp[8];
# Line 774  Line 778 
778                  Data.qpel = Data.chroma = 0;                  Data.qpel = Data.chroma = 0;
779          }          }
780    
781          if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)          Data.RefQ = pRefV->u; // a good place, also used in MC (for similar purpose)
                 return 1; // allocate some mem for qpel interpolated blocks  
                                   // somehow this is dirty since I think we shouldn't use malloc outside  
                                   // encoder_create() - so please fix me!  
         Data.RefQ = qimage;  
782          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
783    
784          for (y = 0; y < mb_height; y++) {          for (y = 0; y < mb_height; y++) {
# Line 870  Line 870 
870                                                    pParam->edged_width);                                                    pParam->edged_width);
871    
872                                          if (deviation < (pMB->sad16 - InterBias)) {                                          if (deviation < (pMB->sad16 - InterBias)) {
873                                          if (++iIntra >= iLimit) { free(qimage); return 1; }                                          if (++iIntra >= iLimit) return 1;
874                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
875                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
876                                                          pMB->mvs[3] = zeroMV;                                                          pMB->mvs[3] = zeroMV;
# Line 882  Line 882 
882                          }                          }
883                  }                  }
884          }          }
         free(qimage);  
885    
886          if (current->coding_type == S_VOP)      /* first GMC step only for S(GMC)-VOPs */          if (current->coding_type == S_VOP)      /* first GMC step only for S(GMC)-VOPs */
887                  current->GMC_MV = GlobalMotionEst( pMBs, pParam, current->fcode );                  current->GMC_MV = GlobalMotionEst( pMBs, pParam, current->fcode );
# Line 933  Line 932 
932      else pmv[4].x = pmv[4].y = 0;      else pmv[4].x = pmv[4].y = 0;
933    
934          // [1] median prediction          // [1] median prediction
935          if (rrv) { //median is in halfzero-precision          pmv[1].x = EVEN(pmv[0].x); pmv[1].y = EVEN(pmv[0].y);
                 pmv[1].x = RRV_MV_SCALEUP(pmv[0].x);  
                 pmv[1].y = RRV_MV_SCALEUP(pmv[0].y);  
         } else { pmv[1].x = EVEN(pmv[0].x); pmv[1].y = EVEN(pmv[0].y); }  
936    
937          pmv[0].x = pmv[0].y = 0; // [0] is zero; not used in the loop (checked before) but needed here for make_mask          pmv[0].x = pmv[0].y = 0; // [0] is zero; not used in the loop (checked before) but needed here for make_mask
938    
# Line 951  Line 947 
947          if (rrv) {          if (rrv) {
948                  int i;                  int i;
949                  for (i = 0; i < 7; i++) {                  for (i = 0; i < 7; i++) {
950                          pmv[i].x = RRV_MV_SCALEDOWN(pmv[i].x);                          pmv[i].x = RRV_MV_SCALEUP(pmv[i].x); // halfzero->halfpel
951                          pmv[i].x = RRV_MV_SCALEUP(pmv[i].x); // a trick                          pmv[i].y = RRV_MV_SCALEUP(pmv[i].y);
952                  }                  }
953          }          }
954  }  }
# Line 1094  Line 1090 
1090                  Data->currentQMV[i].y = 2 * Data->currentMV[i].y;                  Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1091          }          }
1092    
1093          if((!Data->rrv) && (pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {          if((Data->qpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1094    
1095                  Data->qpel_precision = 1;                  Data->qpel_precision = 1;
1096                  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,
# Line 1118  Line 1114 
1114                  Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);                  Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1115    
1116                  if (Data->chroma) {                  if (Data->chroma) {
1117                          int sumx, sumy, dx, dy;                          int sumx, sumy;
1118    
1119                          if(pParam->m_quarterpel) {                          if(pParam->m_quarterpel) {
1120                                  sumx= pMB->qmvs[0].x/2 + pMB->qmvs[1].x/2 + pMB->qmvs[2].x/2 + pMB->qmvs[3].x/2;                                  sumx= pMB->qmvs[0].x/2 + pMB->qmvs[1].x/2 + pMB->qmvs[2].x/2 + pMB->qmvs[3].x/2;
# Line 1127  Line 1123 
1123                                  sumx = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;                                  sumx = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1124                                  sumy = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;                                  sumy = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1125                          }                          }
                         dx = (sumx >> 3) + roundtab_76[sumx & 0xf];  
                         dy = (sumy >> 3) + roundtab_76[sumy & 0xf];  
1126    
1127                          Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);                          Data->iMinSAD[1] += ChromaSAD(  (sumx >> 3) + roundtab_76[sumx & 0xf],
1128                                                                                            (sumy >> 3) + roundtab_76[sumy & 0xf], Data);
1129                  }                  }
1130          }          }
1131    
# Line 1138  Line 1133 
1133                          Data->currentMV[0].x = RRV_MV_SCALEDOWN(Data->currentMV[0].x);                          Data->currentMV[0].x = RRV_MV_SCALEDOWN(Data->currentMV[0].x);
1134                          Data->currentMV[0].y = RRV_MV_SCALEDOWN(Data->currentMV[0].y);                          Data->currentMV[0].y = RRV_MV_SCALEDOWN(Data->currentMV[0].y);
1135          }          }
1136    
1137          if (!(inter4v) ||          if (!(inter4v) ||
1138                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
1139                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
# Line 1240  Line 1236 
1236                          }                          }
1237                  }                  }
1238    
1239                  if(!Data->rrv && Data->qpel) {                  if(Data->qpel) {
1240                          if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&                          if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1241                                  (MotionFlags & PMV_QUARTERPELREFINE8)) {                                  (MotionFlags & PMV_QUARTERPELREFINE8)) {
1242                          Data->qpel_precision = 1;                          Data->qpel_precision = 1;
# Line 1311  Line 1307 
1307    
1308          if ((x != 0)&&(y != 0)) {          if ((x != 0)&&(y != 0)) {
1309                  pmv[6] = ChoosePred(pMB-1-iWcount, mode_curr);                  pmv[6] = ChoosePred(pMB-1-iWcount, mode_curr);
1310                  pmv[6].x = EVEN(pmv[5].x); pmv[5].y = EVEN(pmv[5].y);                  pmv[6].x = EVEN(pmv[6].x); pmv[6].y = EVEN(pmv[6].y);
1311          } else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
1312    
1313  // more?  // more?
# Line 1338  Line 1334 
1334    
1335          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1336    
1337          int i, iDirection, mask;          int i, iDirection = 255, mask;
1338          VECTOR pmv[7];          VECTOR pmv[7];
1339          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1340          *Data->iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
# Line 1363  Line 1359 
1359          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1360    
1361  // main loop. checking all predictions  // main loop. checking all predictions
1362          for (i = 0; i < 8; i++) {          for (i = 0; i < 7; i++) {
1363                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1364                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1365          }          }
# Line 1374  Line 1370 
1370                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1371                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1372    
1373          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1374    
1375          SubpelRefine(Data);          SubpelRefine(Data);
1376    
1377          if (Data->qpel) {          if (Data->qpel && *Data->iMinSAD < *best_sad + 300) {
1378                  Data->currentQMV->x = 2*Data->currentMV->x;                  Data->currentQMV->x = 2*Data->currentMV->x;
1379                  Data->currentQMV->y = 2*Data->currentMV->y;                  Data->currentQMV->y = 2*Data->currentMV->y;
1380                  Data->qpel_precision = 1;                  Data->qpel_precision = 1;
# Line 1388  Line 1384 
1384          }          }
1385    
1386  // three bits are needed to code backward mode. four for forward  // three bits are needed to code backward mode. four for forward
1387  // we treat the bits just like they were vector's  
1388          if (mode_current == MODE_FORWARD) *Data->iMinSAD +=  4 * Data->lambda16;          if (mode_current == MODE_FORWARD) *Data->iMinSAD +=  4 * Data->lambda16;
1389          else *Data->iMinSAD +=  3 * Data->lambda16;          else *Data->iMinSAD +=  3 * Data->lambda16;
1390    
# Line 1419  Line 1415 
1415                            const IMAGE * const f_Ref,                            const IMAGE * const f_Ref,
1416                            const IMAGE * const b_Ref,                            const IMAGE * const b_Ref,
1417                            MACROBLOCK * const pMB,                            MACROBLOCK * const pMB,
                           const uint32_t quant,  
1418                            const uint32_t x, const uint32_t y,                            const uint32_t x, const uint32_t y,
1419                            const SearchData * const Data)                            const SearchData * const Data)
1420  {  {
1421          int dx, dy, b_dx, b_dy;          int dx = 0, dy = 0, b_dx = 0, b_dy = 0;
1422          uint32_t sum;          uint32_t sum;
1423            const int div = 1 + Data->qpel;
1424            int k;
1425            const uint32_t quant = pMB->quant;
1426  //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
         if (Data->qpel) {  
                 dy = Data->directmvF[0].y/2 + Data->directmvF[1].y/2 +  
                                 Data->directmvF[2].y/2 + Data->directmvF[3].y/2;  
   
                 dx = Data->directmvF[0].x/2 + Data->directmvF[1].x/2 +  
                                 Data->directmvF[2].x/2 + Data->directmvF[3].x/2;  
1427    
1428                  b_dy = Data->directmvB[0].y/2 + Data->directmvB[1].y/2 +          for (k = 0; k < 4; k++) {
1429                                  Data->directmvB[2].y/2 + Data->directmvB[3].y/2;                  dy += Data->directmvF[k].y / div;
1430                    dx += Data->directmvF[0].x / div;
1431                  b_dx = Data->directmvB[0].x/2 + Data->directmvB[1].x/2 +                  b_dy += Data->directmvB[0].y / div;
1432                                  Data->directmvB[2].x/2 + Data->directmvB[3].x/2;                  b_dx += Data->directmvB[0].x / div;
   
         } else {  
                 dy = Data->directmvF[0].y + Data->directmvF[1].y +  
                                 Data->directmvF[2].y + Data->directmvF[3].y;  
   
                 dx = Data->directmvF[0].x + Data->directmvF[1].x +  
                                 Data->directmvF[2].x + Data->directmvF[3].x;  
   
                 b_dy = Data->directmvB[0].y + Data->directmvB[1].y +  
                                 Data->directmvB[2].y + Data->directmvB[3].y;  
   
                 b_dx = Data->directmvB[0].x + Data->directmvB[1].x +  
                                 Data->directmvB[2].x + Data->directmvB[3].x;  
1433          }          }
1434    
   
1435          dy = (dy >> 3) + roundtab_76[dy & 0xf];          dy = (dy >> 3) + roundtab_76[dy & 0xf];
1436          dx = (dx >> 3) + roundtab_76[dx & 0xf];          dx = (dx >> 3) + roundtab_76[dx & 0xf];
1437          b_dy = (b_dy >> 3) + roundtab_76[b_dy & 0xf];          b_dy = (b_dy >> 3) + roundtab_76[b_dy & 0xf];
# Line 1463  Line 1441 
1441                                          f_Ref->u + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,                                          f_Ref->u + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1442                                          b_Ref->u + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,                                          b_Ref->u + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1443                                          Data->iEdgedWidth/2);                                          Data->iEdgedWidth/2);
1444    
1445            if (sum >= 2 * MAX_CHROMA_SAD_FOR_SKIP * quant) return; //no skip
1446    
1447          sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),          sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1448                                          f_Ref->v + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,                                          f_Ref->v + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1449                                          b_Ref->v + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,                                          b_Ref->v + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
# Line 1552  Line 1533 
1533    
1534  // initial (fast) skip decision  // initial (fast) skip decision
1535          if (*Data->iMinSAD < pMB->quant * INITIAL_SKIP_THRESH*2) {          if (*Data->iMinSAD < pMB->quant * INITIAL_SKIP_THRESH*2) {
1536                  SkipDecisionB(pCur, f_Ref, b_Ref, pMB, x, y, Data->chroma, Data); //possible skip - checking chroma                  SkipDecisionB(pCur, f_Ref, b_Ref, pMB, x, y, Data); //possible skip - checking chroma
1537                  if (pMB->mode == MODE_DIRECT_NONE_MV) return *Data->iMinSAD; // skip.                  if (pMB->mode == MODE_DIRECT_NONE_MV) return *Data->iMinSAD; // skip.
1538          }          }
1539    
# Line 1571  Line 1552 
1552    
1553          *best_sad = *Data->iMinSAD;          *best_sad = *Data->iMinSAD;
1554    
1555          if (b_mb->mode == MODE_INTER4V) pMB->mode = MODE_DIRECT;          if (b_mb->mode == MODE_INTER4V || Data->qpel) pMB->mode = MODE_DIRECT;
1556          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1557    
1558          pMB->pmvs[3] = *Data->currentMV;          pMB->pmvs[3] = *Data->currentMV;
# Line 1688  Line 1669 
1669          } while (!(iDirection));          } while (!(iDirection));
1670    
1671          if (fData->qpel) {          if (fData->qpel) {
1672                    if (*fData->iMinSAD > *best_sad + 500) return;
1673                  CheckCandidate = CheckCandidateInt;                  CheckCandidate = CheckCandidateInt;
1674                  fData->qpel_precision = bData.qpel_precision = 1;                  fData->qpel_precision = bData.qpel_precision = 1;
1675                  get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, 1, 0);                  get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, 1, 0);
# Line 1697  Line 1679 
1679                  fData->currentQMV[1].x = 2 * fData->currentMV[1].x;                  fData->currentQMV[1].x = 2 * fData->currentMV[1].x;
1680                  fData->currentQMV[1].y = 2 * fData->currentMV[1].y;                  fData->currentQMV[1].y = 2 * fData->currentMV[1].y;
1681                  SubpelRefine(fData);                  SubpelRefine(fData);
1682                    if (*fData->iMinSAD > *best_sad + 300) return;
1683                  fData->currentQMV[2] = fData->currentQMV[0];                  fData->currentQMV[2] = fData->currentQMV[0];
1684                  SubpelRefine(&bData);                  SubpelRefine(&bData);
1685          }          }
1686    
1687          *fData->iMinSAD +=  (2+2) * fData->lambda16; // two bits are needed to code interpolate mode.          *fData->iMinSAD +=  (2+3) * fData->lambda16; // two bits are needed to code interpolate mode.
1688    
1689          if (*fData->iMinSAD < *best_sad) {          if (*fData->iMinSAD < *best_sad) {
1690                  *best_sad = *fData->iMinSAD;                  *best_sad = *fData->iMinSAD;
# Line 1753  Line 1736 
1736    
1737          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1738          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
         uint8_t * qimage;  
1739    
1740  // some pre-inintialized data for the rest of the search  // some pre-inintialized data for the rest of the search
1741    
# Line 1770  Line 1752 
1752          Data.qpel = pParam->m_quarterpel;          Data.qpel = pParam->m_quarterpel;
1753          Data.rounding = 0;          Data.rounding = 0;
1754    
1755          if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)          Data.RefQ = f_refV->u; // a good place, also used in MC (for similar purpose)
                 return; // allocate some mem for qpel interpolated blocks  
                                   // somehow this is dirty since I think we shouldn't use malloc outside  
                                   // encoder_create() - so please fix me!  
         Data.RefQ = qimage;  
   
1756          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
1757          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
1758    
# Line 1841  Line 1818 
1818  // final skip decision  // final skip decision
1819                          if ( (skip_sad < frame->quant * MAX_SAD00_FOR_SKIP*2)                          if ( (skip_sad < frame->quant * MAX_SAD00_FOR_SKIP*2)
1820                                          && ((100*best_sad)/(skip_sad+1) > FINAL_SKIP_THRESH) )                                          && ((100*best_sad)/(skip_sad+1) > FINAL_SKIP_THRESH) )
1821                                  SkipDecisionB(&frame->image, f_ref, b_ref, pMB,frame->quant, i, j, &Data);                                  SkipDecisionB(&frame->image, f_ref, b_ref, pMB, i, j, &Data);
1822    
1823                          switch (pMB->mode) {                          switch (pMB->mode) {
1824                                  case MODE_FORWARD:                                  case MODE_FORWARD:
# Line 1872  Line 1849 
1849                          }                          }
1850                  }                  }
1851          }          }
         free(qimage);  
1852  }  }
1853    
1854  static __inline void  static __inline void
# Line 2070  Line 2046 
2046                  max_x = gmc.x + step;                  max_x = gmc.x + step;
2047                  min_y = gmc.y - step;                  min_y = gmc.y - step;
2048                  max_y = gmc.y + step;                  max_y = gmc.y + step;
   
2049          }          }
2050    
2051          if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10)          if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10)
2052                  gmc.x = gmc.y = 0; //no camara pan, no GMC                  gmc.x = gmc.y = 0; //no camara pan, no GMC
2053    
2054  // step2: let's refine camera panning using gradiend-descent approach.  // step2: let's refine camera panning using gradiend-descent approach
2055  // TODO: more warping points may be evaluated here (like in interpolate mode search - two vectors in one diamond)  // TODO: more warping points may be evaluated here (like in interpolate mode search - two vectors in one diamond)
2056          bestcount = 0;          bestcount = 0;
2057          CheckGMC(gmc.x, gmc.y, 255, &iDirection, pMBs, &bestcount, &gmc, pParam);          CheckGMC(gmc.x, gmc.y, 255, &iDirection, pMBs, &bestcount, &gmc, pParam);

Legend:
Removed from v.739  
changed lines
  Added in v.767

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