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

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

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

revision 539, Wed Sep 25 21:28:48 2002 UTC revision 669, Thu Nov 21 11:07:10 2002 UTC
# Line 37  Line 37 
37  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
38  #include "../global.h"  #include "../global.h"
39  #include "../utils/timer.h"  #include "../utils/timer.h"
40    #include "../image/interpolate8x8.h"
41  #include "motion_est.h"  #include "motion_est.h"
42  #include "motion.h"  #include "motion.h"
43  #include "sad.h"  #include "sad.h"
# Line 78  Line 79 
79          return xb + yb;          return xb + yb;
80  }  }
81    
82    static int32_t
83    ChromaSAD(int dx, int dy, const SearchData * const data)
84    {
85            int sad;
86            dx = (dx >> 1) + roundtab_79[dx & 0x3];
87            dy = (dy >> 1) + roundtab_79[dy & 0x3];
88    
89            switch (((dx & 1) << 1) + (dy & 1))     { // ((dx%2)?2:0)+((dy%2)?1:0)
90                    case 0:
91                            sad = sad8(data->CurU, data->RefCU + (dy/2) * (data->iEdgedWidth/2) + dx/2, data->iEdgedWidth/2);
92                            sad += sad8(data->CurV, data->RefCV + (dy/2) * (data->iEdgedWidth/2) + dx/2, data->iEdgedWidth/2);
93                            break;
94                    case 1:
95                            dx = dx / 2; dy = (dy - 1) / 2;
96                            sad = sad8bi(data->CurU, data->RefCU + dy * (data->iEdgedWidth/2) + dx, data->RefCU + (dy+1) * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2);
97                            sad += sad8bi(data->CurV, data->RefCV + dy * (data->iEdgedWidth/2) + dx, data->RefCV + (dy+1) * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2);
98                            break;
99                    case 2:
100                            dx = (dx - 1) / 2; dy = dy / 2;
101                            sad = sad8bi(data->CurU, data->RefCU + dy * (data->iEdgedWidth/2) + dx, data->RefCU + dy * (data->iEdgedWidth/2) + dx+1, data->iEdgedWidth/2);
102                            sad += sad8bi(data->CurV, data->RefCV + dy * (data->iEdgedWidth/2) + dx, data->RefCV + dy * (data->iEdgedWidth/2) + dx+1, data->iEdgedWidth/2);
103                            break;
104                    default:
105                            dx = (dx - 1) / 2; dy = (dy - 1) / 2;
106                            interpolate8x8_halfpel_hv(data->RefQ,
107                                                                             data->RefCU + dy * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2,
108                                                                             data->rounding);
109                            sad = sad8(data->CurU, data->RefQ, data->iEdgedWidth/2);
110                            interpolate8x8_halfpel_hv(data->RefQ,
111                                                                             data->RefCV + dy * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2,
112                                                                             data->rounding);
113                            sad += sad8(data->CurV, data->RefQ, data->iEdgedWidth/2);
114                            break;
115            }
116            return sad;
117    }
118    
119    static __inline const uint8_t *
120    GetReference(const int x, const int y, const int dir, const SearchData * const data)
121    {
122    //      dir : 0 = forward, 1 = backward
123            switch ( (dir << 2) | ((x&1)<<1) | (y&1) ) {
124                    case 0 : return data->Ref + x/2 + (y/2)*(data->iEdgedWidth);
125                    case 1 : return data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth);
126                    case 2 : return data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth);
127                    case 3 : return data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth);
128                    case 4 : return data->bRef + x/2 + (y/2)*(data->iEdgedWidth);
129                    case 5 : return data->bRefV + x/2 + ((y-1)/2)*(data->iEdgedWidth);
130                    case 6 : return data->bRefH + (x-1)/2 + (y/2)*(data->iEdgedWidth);
131                    default : return data->bRefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth);
132    
133            }
134    }
135    
136    static uint8_t *
137    Interpolate8x8qpel(const int x, const int y, const int block, const int dir, const SearchData * const data)
138    {
139    // create or find a qpel-precision reference picture; return pointer to it
140            uint8_t * Reference = (uint8_t *)data->RefQ + 16*dir;
141            const int32_t iEdgedWidth = data->iEdgedWidth;
142            const uint32_t rounding = data->rounding;
143            const int halfpel_x = x/2;
144            const int halfpel_y = y/2;
145            const uint8_t *ref1, *ref2, *ref3, *ref4;
146    
147            ref1 = GetReference(halfpel_x, halfpel_y, dir, data); // this reference is used in all cases
148            ref1 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
149            switch( ((x&1)<<1) + (y&1) ) {
150            case 0: // pure halfpel position
151                    Reference = (uint8_t *) GetReference(halfpel_x, halfpel_y, dir, data);
152                    Reference += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
153                    break;
154    
155            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
156                    ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);
157                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
158                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
159                    break;
160    
161            case 2: // x qpel, y halfpel - left or right during qpel refinement
162                    ref2 = GetReference(x - halfpel_x, halfpel_y, dir, data);
163                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
164                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
165                    break;
166    
167            default: // x and y in qpel resolution - the "corners" (top left/right and
168                             // bottom left/right) during qpel refinement
169                    ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);
170                    ref3 = GetReference(x - halfpel_x, halfpel_y, dir, data);
171                    ref4 = GetReference(x - halfpel_x, y - halfpel_y, dir, data);
172                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
173                    ref3 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
174                    ref4 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
175                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
176                    break;
177            }
178            return Reference;
179    }
180    
181    static uint8_t *
182    Interpolate16x16qpel(const int x, const int y, const int dir, const SearchData * const data)
183    {
184    // create or find a qpel-precision reference picture; return pointer to it
185            uint8_t * Reference = (uint8_t *)data->RefQ + 16*dir;
186            const int32_t iEdgedWidth = data->iEdgedWidth;
187            const uint32_t rounding = data->rounding;
188            const int halfpel_x = x/2;
189            const int halfpel_y = y/2;
190            const uint8_t *ref1, *ref2, *ref3, *ref4;
191    
192            ref1 = GetReference(halfpel_x, halfpel_y, dir, data); // this reference is used in all cases
193            switch( ((x&1)<<1) + (y&1) ) {
194            case 0: // pure halfpel position
195                    return (uint8_t *) GetReference(halfpel_x, halfpel_y, dir, data);
196            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
197                    ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);
198                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
199                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
200                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
201                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
202                    break;
203    
204            case 2: // x qpel, y halfpel - left or right during qpel refinement
205                    ref2 = GetReference(x - halfpel_x, halfpel_y, dir, data);
206                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
207                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
208                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
209                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
210                    break;
211    
212            default: // x and y in qpel resolution - the "corners" (top left/right and
213                             // bottom left/right) during qpel refinement
214                    ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);
215                    ref3 = GetReference(x - halfpel_x, halfpel_y, dir, data);
216                    ref4 = GetReference(x - halfpel_x, y - halfpel_y, dir, data);
217                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
218                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
219                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
220                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
221                    break;
222            }
223            return Reference;
224    }
225    
226  /* CHECK_CANDIATE FUNCTIONS START */  /* CHECK_CANDIATE FUNCTIONS START */
227    
228  static void  static void
229  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)
230  {  {
231          int32_t * const sad = data->temp;          int t, xc, yc;
         int t;  
232          const uint8_t * Reference;          const uint8_t * Reference;
233            VECTOR * current;
234    
235          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
236                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
237    
238            if (data->qpel_precision) { // x and y are in 1/4 precision
239                    Reference = Interpolate16x16qpel(x, y, 0, data);
240                    t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
241                    xc = x/2; yc = y/2; //for chroma sad
242                    current = data->currentQMV;
243            } else {
244          switch ( ((x&1)<<1) + (y&1) ) {          switch ( ((x&1)<<1) + (y&1) ) {
245                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;
246                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;
247                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;
248                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;
249          }          }
250                    if (data->qpel) t = d_mv_bits(2*x - data->predMV.x, 2*y - data->predMV.y, data->iFcode);
251                    else t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
252                    current = data->currentMV;
253                    xc = x; yc = y;
254            }
255    
256          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, sad+1);          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
257    
258          t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          data->temp[0] += (data->lambda16 * t * data->temp[0])/1000;
259          data->temp[0] += lambda_vec16[data->iQuant] * t;          data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))/100;
260          data->temp[1] += lambda_vec8[data->iQuant] * t;  
261            if (data->chroma) data->temp[0] += ChromaSAD(xc, yc, data);
262    
263          if (data->temp[0] < data->iMinSAD[0]) {          if (data->temp[0] < data->iMinSAD[0]) {
264                  data->iMinSAD[0] = data->temp[0];                  data->iMinSAD[0] = data->temp[0];
265                  data->currentMV[0].x = x; data->currentMV[0].y = y;                  current[0].x = x; current[0].y = y;
266                  *dir = Direction; }                  *dir = Direction; }
267    
268          if (data->temp[1] < data->iMinSAD[1]) {          if (data->temp[1] < data->iMinSAD[1]) {
269                  data->iMinSAD[1] = data->temp[1]; data->currentMV[1].x = x; data->currentMV[1].y = y; }                  data->iMinSAD[1] = data->temp[1]; current[1].x = x; current[1].y= y; }
270          if (data->temp[2] < data->iMinSAD[2]) {          if (data->temp[2] < data->iMinSAD[2]) {
271                  data->iMinSAD[2] = data->temp[2]; data->currentMV[2].x = x; data->currentMV[2].y = y; }                  data->iMinSAD[2] = data->temp[2]; current[2].x = x; current[2].y = y; }
272          if (data->temp[3] < data->iMinSAD[3]) {          if (data->temp[3] < data->iMinSAD[3]) {
273                  data->iMinSAD[3] = data->temp[3]; data->currentMV[3].x = x; data->currentMV[3].y = y; }                  data->iMinSAD[3] = data->temp[3]; current[3].x = x; current[3].y = y; }
274          if (data->temp[4] < data->iMinSAD[4]) {          if (data->temp[4] < data->iMinSAD[4]) {
275                  data->iMinSAD[4] = data->temp[4]; data->currentMV[4].x = x; data->currentMV[4].y = y; }                  data->iMinSAD[4] = data->temp[4]; current[4].x = x; current[4].y = y; }
276    
277  }  }
278    
# Line 125  Line 281 
281  {  {
282          int32_t sad;          int32_t sad;
283          const uint8_t * Reference;          const uint8_t * Reference;
284            int t;
285            VECTOR * current;
286    
287          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
288                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
289    
290          switch ( ((x&1)<<1) + (y&1) )          if (data->qpel_precision) { // x and y are in 1/4 precision
291          {                  Reference = Interpolate16x16qpel(x, y, 0, data);
292                    t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
293                    current = data->currentQMV;
294            } else {
295                    switch ( ((x&1)<<1) + (y&1) ) {
296                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;
297                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;
298                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;
299                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;
300          }          }
301                    if (data->qpel) t = d_mv_bits(2*x - data->predMV.x, 2*y - data->predMV.y, data->iFcode);
302                    else t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
303                    current = data->currentMV;
304            }
305    
306          sad = lambda_vec16[data->iQuant] *          sad = sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);
307                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          sad += (data->lambda16 * t * sad)/1000;
         sad += sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);  
308    
309          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
310                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
311                  data->currentMV[0].x = x; data->currentMV[0].y = y;                  current->x = x; current->y = y;
312                  *dir = Direction; }                  *dir = Direction; }
313  }  }
314    
315  static void  static void
316  CheckCandidate16no4vI(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidate16no4vI(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
317  {  {
318    // maximum speed - for P/B/I decision
319          int32_t sad;          int32_t sad;
320    
321          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
322                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
323    
324          sad = lambda_vec16[data->iQuant] *          sad = sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),
                         d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);  
   
         sad += sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),  
325                                          data->iEdgedWidth, 256*4096);                                          data->iEdgedWidth, 256*4096);
326    
327          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
# Line 172  Line 335 
335  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)
336  {  {
337          int32_t sad;          int32_t sad;
338          const int xb = data->currentMV[1].x;          int xb, yb, t;
         const int yb = data->currentMV[1].y;  
339          const uint8_t *ReferenceF, *ReferenceB;          const uint8_t *ReferenceF, *ReferenceB;
340            VECTOR *current;
341    
342          if (( xf > data->max_dx) || ( xf < data->min_dx)          if (( xf > data->max_dx) || ( xf < data->min_dx)
343                  || ( yf > data->max_dy) || (yf < data->min_dy)) return;                  || ( yf > data->max_dy) || (yf < data->min_dy)) return;
344    
345          switch ( ((xf&1)<<1) + (yf&1) ) {          if (data->qpel_precision) {
346                  case 0 : ReferenceF = data->Ref + xf/2 + (yf/2)*(data->iEdgedWidth); break;                  ReferenceF = Interpolate16x16qpel(xf, yf, 0, data);
347                  case 1 : ReferenceF = data->RefV + xf/2 + ((yf-1)/2)*(data->iEdgedWidth); break;                  xb = data->currentQMV[1].x; yb = data->currentQMV[1].y;
348                  case 2 : ReferenceF = data->RefH + (xf-1)/2 + (yf/2)*(data->iEdgedWidth); break;                  current = data->currentQMV;
349                  default : ReferenceF = data->RefHV + (xf-1)/2 + ((yf-1)/2)*(data->iEdgedWidth); break;                  ReferenceB = Interpolate16x16qpel(xb, yb, 1, data);
350          }                  t = d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode)
351                                     + d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode);
352          switch ( ((xb&1)<<1) + (yb&1) ) {          } else {
353                  case 0 : ReferenceB = data->bRef + xb/2 + (yb/2)*(data->iEdgedWidth); break;                  ReferenceF = Interpolate16x16qpel(2*xf, 2*yf, 0, data);
354                  case 1 : ReferenceB = data->bRefV + xb/2 + ((yb-1)/2)*(data->iEdgedWidth); break;                  xb = data->currentMV[1].x; yb = data->currentMV[1].y;
355                  case 2 : ReferenceB = data->bRefH + (xb-1)/2 + (yb/2)*(data->iEdgedWidth); break;                  ReferenceB = Interpolate16x16qpel(2*xb, 2*yb, 1, data);
356                  default : ReferenceB = data->bRefHV + (xb-1)/2 + ((yb-1)/2)*(data->iEdgedWidth); break;                  current = data->currentMV;
357                    if (data->qpel)
358                            t = d_mv_bits(2*xf - data->predMV.x, 2*yf - data->predMV.y, data->iFcode)
359                                             + d_mv_bits(2*xb - data->bpredMV.x, 2*yb - data->bpredMV.y, data->iFcode);
360                    else
361                            t = d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode)
362                                             + d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode);
363          }          }
364    
365          sad = lambda_vec16[data->iQuant] *          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
366                          ( d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode) +          sad += (data->lambda16 * t * sad)/1000;
                           d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode) );  
   
         sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);  
367    
368          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
369                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
370                  data->currentMV->x = xf; data->currentMV->y = yf;                  current->x = xf; current->y = yf;
371                  *dir = Direction; }                  *dir = Direction; }
372  }  }
373    
374  static void  static void
375  CheckCandidateDirect(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidateDirect(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
376  {  {
377          int32_t sad;          int32_t sad = 0;
378          int k;          int k;
379          const uint8_t *ReferenceF;          const uint8_t *ReferenceF;
380          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
# Line 216  Line 382 
382    
383          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
384    
         sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);  
   
385          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
386                  mvs.x = data->directmvF[k].x + x;                  mvs.x = data->directmvF[k].x + x;
387                  b_mvs.x = ((x == 0) ?                  b_mvs.x = ((x == 0) ?
# Line 234  Line 398 
398                          || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )                          || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )
399                          || ( b_mvs.y > data->max_dy ) || ( b_mvs.y < data->min_dy )) return;                          || ( b_mvs.y > data->max_dy ) || ( b_mvs.y < data->min_dy )) return;
400    
401                  switch ( ((mvs.x&1)<<1) + (mvs.y&1) ) {                  if (!data->qpel) {
402                          case 0 : ReferenceF = data->Ref + mvs.x/2 + (mvs.y/2)*(data->iEdgedWidth); break;                          mvs.x *= 2; mvs.y *= 2;
403                          case 1 : ReferenceF = data->RefV + mvs.x/2 + ((mvs.y-1)/2)*(data->iEdgedWidth); break;                          b_mvs.x *= 2; b_mvs.y *= 2; //we move to qpel precision anyway
                         case 2 : ReferenceF = data->RefH + (mvs.x-1)/2 + (mvs.y/2)*(data->iEdgedWidth); break;  
                         default : ReferenceF = data->RefHV + (mvs.x-1)/2 + ((mvs.y-1)/2)*(data->iEdgedWidth); break;  
                 }  
   
                 switch ( ((b_mvs.x&1)<<1) + (b_mvs.y&1) ) {  
                         case 0 : ReferenceB = data->bRef + b_mvs.x/2 + (b_mvs.y/2)*(data->iEdgedWidth); break;  
                         case 1 : ReferenceB = data->bRefV + b_mvs.x/2 + ((b_mvs.y-1)/2)*(data->iEdgedWidth); break;  
                         case 2 : ReferenceB = data->bRefH + (b_mvs.x-1)/2 + (b_mvs.y/2)*(data->iEdgedWidth); break;  
                         default : ReferenceB = data->bRefHV + (b_mvs.x-1)/2 + ((b_mvs.y-1)/2)*(data->iEdgedWidth); break;  
404                  }                  }
405                    ReferenceF = Interpolate8x8qpel(mvs.x, mvs.y, k, 0, data);
406                    ReferenceB = Interpolate8x8qpel(b_mvs.x, b_mvs.y, k, 1, data);
407    
408                  sad += sad8bi(data->Cur + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),                  sad += sad8bi(data->Cur + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
409                                                  ReferenceF + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),                                                  ReferenceF, ReferenceB,
                                                 ReferenceB + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),  
410                                                  data->iEdgedWidth);                                                  data->iEdgedWidth);
411                  if (sad > *(data->iMinSAD)) return;                  if (sad > *(data->iMinSAD)) return;
412          }          }
413    
414            sad += (data->lambda16 * d_mv_bits(x, y, 1) * sad)/1000;
415    
416          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
417                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
418                  data->currentMV->x = x; data->currentMV->y = y;                  data->currentMV->x = x; data->currentMV->y = y;
# Line 269  Line 427 
427          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
428          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
429    
430          if (( x > 31) || ( x < -31) || ( y > 31) || (y < -31)) return;          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
   
                 sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);  
431    
432          mvs.x = data->directmvF[0].x + x;          mvs.x = data->directmvF[0].x + x;
433          b_mvs.x = ((x == 0) ?          b_mvs.x = ((x == 0) ?
# Line 288  Line 444 
444                  || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )                  || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )
445                  || ( b_mvs.y > data->max_dy ) || ( b_mvs.y < data->min_dy )) return;                  || ( b_mvs.y > data->max_dy ) || ( b_mvs.y < data->min_dy )) return;
446    
447          switch ( ((mvs.x&1)<<1) + (mvs.y&1) ) {          if (!data->qpel) {
448                  case 0 : ReferenceF = data->Ref + mvs.x/2 + (mvs.y/2)*(data->iEdgedWidth); break;                          mvs.x *= 2; mvs.y *= 2;
449                  case 1 : ReferenceF = data->RefV + mvs.x/2 + ((mvs.y-1)/2)*(data->iEdgedWidth); break;                          b_mvs.x *= 2; b_mvs.y *= 2; //we move to qpel precision anyway
                 case 2 : ReferenceF = data->RefH + (mvs.x-1)/2 + (mvs.y/2)*(data->iEdgedWidth); break;  
                 default : ReferenceF = data->RefHV + (mvs.x-1)/2 + ((mvs.y-1)/2)*(data->iEdgedWidth); break;  
450          }          }
451            ReferenceF = Interpolate16x16qpel(mvs.x, mvs.y, 0, data);
452            ReferenceB = Interpolate16x16qpel(b_mvs.x, b_mvs.y, 1, data);
453    
454          switch ( ((b_mvs.x&1)<<1) + (b_mvs.y&1) ) {          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
455                  case 0 : ReferenceB = data->bRef + b_mvs.x/2 + (b_mvs.y/2)*(data->iEdgedWidth); break;          sad += (data->lambda16 * d_mv_bits(x, y, 1) * sad)/1000;
                 case 1 : ReferenceB = data->bRefV + b_mvs.x/2 + ((b_mvs.y-1)/2)*(data->iEdgedWidth); break;  
                 case 2 : ReferenceB = data->bRefH + (b_mvs.x-1)/2 + (b_mvs.y/2)*(data->iEdgedWidth); break;  
                 default : ReferenceB = data->bRefHV + (b_mvs.x-1)/2 + ((b_mvs.y-1)/2)*(data->iEdgedWidth); break;  
         }  
   
         sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);  
456    
457          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
458                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 313  Line 463 
463  static void  static void
464  CheckCandidate8(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidate8(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
465  {  {
466          int32_t sad;          int32_t sad; int t;
467          const uint8_t * Reference;          const uint8_t * Reference;
468    
469          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
470                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
471    
472          switch ( ((x&1)<<1) + (y&1) )          if (data->qpel) Reference = Interpolate16x16qpel(x, y, 0, data);
473          {          else Reference = Interpolate16x16qpel(2*x, 2*y, 0, data);
                 case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;  
                 case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;  
                 case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;  
                 default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;  
         }  
474    
475          sad = sad8(data->Cur, Reference, data->iEdgedWidth);          sad = sad8(data->Cur, Reference, data->iEdgedWidth);
476          sad += lambda_vec8[data->iQuant] * d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          if (data->qpel) t = d_mv_bits(2 * x - data->predMV.x, 2 * y - data->predMV.y, data->iFcode);
477            else t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
478    
479            sad += (data->lambda8 * t * (sad+NEIGH_8X8_BIAS))/100;
480    
481          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
482                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 485  Line 633 
633  /* HALFPELREFINE COULD BE A MAINSEARCH FUNCTION, BUT THERE IS NO NEED FOR IT */  /* HALFPELREFINE COULD BE A MAINSEARCH FUNCTION, BUT THERE IS NO NEED FOR IT */
634    
635  static void  static void
636  HalfpelRefine(const SearchData * const data)  SubpelRefine(const SearchData * const data)
637  {  {
638  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a half-pel or q-pel refinement */
639            VECTOR backupMV;
         VECTOR backupMV = *(data->currentMV);  
640          int iDirection; //not needed          int iDirection; //not needed
641    
642            if (data->qpel_precision)
643                    backupMV = *(data->currentQMV);
644            else backupMV = *(data->currentMV);
645    
646          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);
647          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);
648          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);
# Line 517  Line 668 
668          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,
669                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);
670          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
671          sadC += sad8(current->v + x*8 + y*(iEdgedWidth/2)*8,          sadC += sad8(current->v + (x + y*(iEdgedWidth/2))*8,
672                                          reference->v + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                          reference->v + (x + y*(iEdgedWidth/2))*8, iEdgedWidth/2);
673          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
674    
675          return 1;          return 1;
# Line 530  Line 681 
681          pMB->mode = MODE_NOT_CODED;          pMB->mode = MODE_NOT_CODED;
682          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;
683          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;
684    
685            pMB->qmvs[0].x = pMB->qmvs[1].x = pMB->qmvs[2].x = pMB->qmvs[3].x = 0;
686            pMB->qmvs[0].y = pMB->qmvs[1].y = pMB->qmvs[2].y = pMB->qmvs[3].y = 0;
687    
688          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;
689  }  }
690    
# Line 550  Line 705 
705    
706          uint32_t x, y;          uint32_t x, y;
707          uint32_t iIntra = 0;          uint32_t iIntra = 0;
708          int32_t InterBias;          int32_t InterBias, quant = current->quant, sad00;
709            uint8_t *qimage;
710    
711          // some pre-initialized thingies for SearchP          // some pre-initialized thingies for SearchP
712          int32_t temp[5];          int32_t temp[5];
713          VECTOR currentMV[5];          VECTOR currentMV[5];
714            VECTOR currentQMV[5];
715          int32_t iMinSAD[5];          int32_t iMinSAD[5];
716          SearchData Data;          SearchData Data;
717          Data.iEdgedWidth = pParam->edged_width;          Data.iEdgedWidth = pParam->edged_width;
718          Data.currentMV = currentMV;          Data.currentMV = currentMV;
719            Data.currentQMV = currentQMV;
720          Data.iMinSAD = iMinSAD;          Data.iMinSAD = iMinSAD;
721          Data.temp = temp;          Data.temp = temp;
722          Data.iFcode = current->fcode;          Data.iFcode = current->fcode;
723            Data.rounding = pParam->m_rounding_type;
724            Data.qpel = pParam->m_quarterpel;
725            Data.chroma = current->global_flags & XVID_ME_COLOUR;
726    
727            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
728                    return 1; // allocate some mem for qpel interpolated blocks
729                                      // somehow this is dirty since I think we shouldn't use malloc outside
730                                      // encoder_create() - so please fix me!
731            Data.RefQ = qimage;
732          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
733    
734          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
735                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
   
736                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
737                          int32_t sad00 =  pMB->sad16  
738                            pMB->sad16
739                                  = sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,                                  = sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,
740                                                          pRef->y + (x + y * pParam->edged_width) * 16,                                                          pRef->y + (x + y * pParam->edged_width) * 16,
741                                                          pParam->edged_width, pMB->sad8 );                                                          pParam->edged_width, pMB->sad8 );
742    
743                            if (Data.chroma) {
744                                    pMB->sad16 += sad8(pCurrent->u + x*8 + y*(pParam->edged_width/2)*8,
745                                                                    pRef->u + x*8 + y*(pParam->edged_width/2)*8, pParam->edged_width/2);
746    
747                                    pMB->sad16 += sad8(pCurrent->v + (x + y*(pParam->edged_width/2))*8,
748                                                                    pRef->v + (x + y*(pParam->edged_width/2))*8, pParam->edged_width/2);
749                            }
750    
751                            sad00 = pMB->sad16; //if no gmc; else sad00 = (..)
752    
753                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
754                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
755                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant;
756                            } else {
757                                    if (pMB->dquant != NO_CHANGE) {
758                                            quant += DQtab[pMB->dquant];
759                                            if (quant > 31) quant = 31;
760                                            else if (quant < 1) quant = 1;
761                                    }
762                                    pMB->quant = quant;
763                            }
764    
765  //initial skip decision  //initial skip decision
766    /* no early skip for GMC (global vector = skip vector is unknown!)  */
767                          if ((pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)                          if (current->coding_type == P_VOP)      { /* no fast SKIP for S(GMC)-VOPs */
768                                  && (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) ) {                                  if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * INITIAL_SKIP_THRESH)
769                                  if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {                                          if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
770                                                  SkipMacroblockP(pMB, sad00);                                                  SkipMacroblockP(pMB, sad00);
771                                                  continue;                                                  continue;
772                                  }                                  }
773                          } else sad00 = 256*4096; // skip not allowed - for final skip decision                          }
774    
775                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchP(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
776                                                  y, current->motion_flags, pMB->quant,                                                  y, current->motion_flags, pMB->quant,
777                                                  &Data, pParam, pMBs, reference->mbs,                                                  &Data, pParam, pMBs, reference->mbs,
778                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
779    
780  /* 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?" */
781                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)                          if (current->coding_type == P_VOP)      {
782                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)                                  if ( (pMB->dquant == NO_CHANGE) && (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)
783                                  { SkipMacroblockP(pMB, sad00); continue; }                                  && ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH) )
784                                            if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
785                                                    SkipMacroblockP(pMB, sad00);
786                                                    continue;
787                                            }
788                            }
789    
790  /* finally, intra decision */  /* finally, intra decision */
791    
792                          InterBias = MV16_INTER_BIAS;                          InterBias = MV16_INTER_BIAS;
793                          if (pMB->quant > 8)  InterBias += 50 * (pMB->quant - 8); // to make high quants work                          if (pMB->quant > 8)  InterBias += 100 * (pMB->quant - 8); // to make high quants work
794                          if (y != 0)                          if (y != 0)
795                                  if ((pMB - pParam->mb_width)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - pParam->mb_width)->mode == MODE_INTRA ) InterBias -= 80;
796                          if (x != 0)                          if (x != 0)
797                                  if ((pMB - 1)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - 1)->mode == MODE_INTRA ) InterBias -= 80;
798    
799                            if (Data.chroma) InterBias += 50; // to compensate bigger SAD
800    
801                          if (InterBias < pMB->sad16)  {                          if (InterBias < pMB->sad16)  {
802                                  const int32_t deviation =                                  const int32_t deviation =
# Line 613  Line 804 
804                                                    pParam->edged_width);                                                    pParam->edged_width);
805    
806                                  if (deviation < (pMB->sad16 - InterBias)) {                                  if (deviation < (pMB->sad16 - InterBias)) {
807                                          if (++iIntra >= iLimit) return 1;                                          if (++iIntra >= iLimit) { free(qimage); return 1; }
808                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
809                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
810                                                          pMB->mvs[3] = zeroMV;                                                          pMB->mvs[3] = zeroMV;
811                                            pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] =
812                                                            pMB->qmvs[3] = zeroMV;
813                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
814                                                  pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
815                                  }                                  }
816                          }                          }
817                  }                  }
818          }          }
819            free(qimage);
820    
821            if (current->coding_type == S_VOP)      /* first GMC step only for S(GMC)-VOPs */
822                    current->GMC_MV = GlobalMotionEst( pMBs, pParam, current->fcode );
823            else
824                    current->GMC_MV = zeroMV;
825    
826          return 0;          return 0;
827  }  }
828    
# Line 680  Line 880 
880  }  }
881    
882  static void  static void
883  SearchP(const uint8_t * const pRef,  SearchP(const IMAGE * const pRef,
884                  const uint8_t * const pRefH,                  const uint8_t * const pRefH,
885                  const uint8_t * const pRefV,                  const uint8_t * const pRefV,
886                  const uint8_t * const pRefHV,                  const uint8_t * const pRefHV,
# Line 702  Line 902 
902    
903          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()
904          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,
905                                  pParam->width, pParam->height, Data->iFcode);                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
906    
         Data->predMV = pmv[0];  
907          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
908          Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8;
909            Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8;
910    
911            Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16;
912          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
913          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
914          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
915            Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
916            Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
917    
918          Data->iQuant = iQuant;          Data->lambda16 = lambda_vec16[iQuant];
919            Data->lambda8 = lambda_vec8[iQuant];
920            Data->qpel_precision = 0;
921    
922          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
923                  Data->min_dx = EVEN(Data->min_dx);                  Data->min_dx = EVEN(Data->min_dx);
# Line 719  Line 925 
925                  Data->min_dy = EVEN(Data->min_dy);                  Data->min_dy = EVEN(Data->min_dy);
926                  Data->max_dy = EVEN(Data->max_dy); }                  Data->max_dy = EVEN(Data->max_dy); }
927    
928          for(i = 0;  i < 5; i++) Data->iMinSAD[i] = 256*4096;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
   
         if (inter4v) CheckCandidate = CheckCandidate16;  
         else CheckCandidate = CheckCandidate16no4v;  
929    
930          (*CheckCandidate)(Data->predMV.x, Data->predMV.y, 0, &iDirection, Data);          for(i = 0;  i < 5; i++)
931                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
932    
933          for(i = 0;  i < 5; i++) Data->currentMV[i].x = Data->currentMV[i].y = 0;          if (pParam->m_quarterpel) Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
934            else Data->predMV = pmv[0];
935    
936          i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);          i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);
937          Data->iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;          Data->iMinSAD[0] = pMB->sad16 + (Data->lambda16 * i * pMB->sad16)/1000;
938          Data->iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;          Data->iMinSAD[1] = pMB->sad8[0] + (Data->lambda8 * i * (pMB->sad8[0]+NEIGH_8X8_BIAS))/100;
939          Data->iMinSAD[2] = pMB->sad8[1];          Data->iMinSAD[2] = pMB->sad8[1];
940          Data->iMinSAD[3] = pMB->sad8[2];          Data->iMinSAD[3] = pMB->sad8[2];
941          Data->iMinSAD[4] = pMB->sad8[3];          Data->iMinSAD[4] = pMB->sad8[3];
942    
         if (pMB->dquant != NO_CHANGE) inter4v = 0;  
   
943          if ((x == 0) && (y == 0)) threshA = 512;          if ((x == 0) && (y == 0)) threshA = 512;
944          else {          else {
945                  threshA = Data->temp[0] + 20;                  threshA = Data->temp[0]; // that's when we keep this SAD atm
946                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
947                  if (threshA > 1024) threshA = 1024; }                  if (threshA > 1024) threshA = 1024; }
948    
949          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,
950                                          prevMBs + x + y * pParam->mb_width);                                          prevMBs + x + y * pParam->mb_width);
951    
952            if (inter4v || Data->chroma) CheckCandidate = CheckCandidate16;
953            else CheckCandidate = CheckCandidate16no4v; //for extra speed
954    
955  /* main loop. checking all predictions */  /* main loop. checking all predictions */
956    
957          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
958                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
959                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, Data);                  (*CheckCandidate)(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
960                  if (Data->iMinSAD[0] <= threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
961          }          }
962    
# Line 779  Line 985 
985                          if (!(MVequal(startMV, backupMV))) {                          if (!(MVequal(startMV, backupMV))) {
986                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
987    
988                                  CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
989                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
990                                  if (bSAD < Data->iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
991                                          Data->currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
# Line 792  Line 998 
998                          if (!(MVequal(startMV, backupMV))) {                          if (!(MVequal(startMV, backupMV))) {
999                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1000    
1001                                  CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1002                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1003                                  if (bSAD < Data->iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1004                                          Data->currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
# Line 801  Line 1007 
1007                  }                  }
1008          }          }
1009    
1010          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);          if (MotionFlags & PMV_HALFPELREFINE16) SubpelRefine(Data);
1011    
1012            for(i = 0; i < 5; i++) {
1013                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1014                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1015            }
1016    
1017            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1018    
1019                    Data->qpel_precision = 1;
1020                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1021                                    pParam->width, pParam->height, Data->iFcode, 0);
1022    
1023                    SubpelRefine(Data);
1024            }
1025    
1026            if (Data->iMinSAD[0] < (int32_t)iQuant * 30 ) inter4v = 0;
1027          if (inter4v) {          if (inter4v) {
1028                  SearchData Data8;                  SearchData Data8;
1029                  Data8.iFcode = Data->iFcode;                  Data8.iFcode = Data->iFcode;
1030                  Data8.iQuant = Data->iQuant;                  Data8.lambda8 = Data->lambda8;
1031                  Data8.iEdgedWidth = Data->iEdgedWidth;                  Data8.iEdgedWidth = Data->iEdgedWidth;
1032                    Data8.RefQ = Data->RefQ;
1033                    Data8.qpel = Data->qpel;
1034                  Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);                  Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1035                  Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);                  Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1036                  Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);                  Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1037                  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);
1038    
1039                    if (Data->chroma) {
1040                            int sumx, sumy, dx, dy;
1041    
1042                            if(pParam->m_quarterpel) {
1043                                    sumx= pMB->qmvs[0].x/2 + pMB->qmvs[1].x/2 + pMB->qmvs[2].x/2 + pMB->qmvs[3].x/2;
1044                                    sumy = pMB->qmvs[0].y/2 + pMB->qmvs[1].y/2 + pMB->qmvs[2].y/2 + pMB->qmvs[3].y/2;
1045                            } else {
1046                                    sumx = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1047                                    sumy = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1048                            }
1049                            dx = (sumx >> 3) + roundtab_76[sumx & 0xf];
1050                            dy = (sumy >> 3) + roundtab_76[sumy & 0xf];
1051    
1052                            Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);
1053                    }
1054          }          }
1055    
1056          if (!(inter4v) ||          if (!(inter4v) ||
# Line 825  Line 1064 
1064                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1065                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1066    
1067                    if(pParam->m_quarterpel) {
1068                            pMB->qmvs[0] = pMB->qmvs[1]
1069                                    = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1070                            pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predMV.x;
1071                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predMV.y;
1072                    } else {
1073                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1074                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1075                    }
1076          } else {          } else {
1077  // INTER4V MODE; all other things are already set in Search8  // INTER4V MODE; all other things are already set in Search8
1078                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1079                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1080                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1081          }          }
   
1082  }  }
1083    
1084  static void  static void
# Line 846  Line 1091 
1091                  const int block,                  const int block,
1092                  SearchData * const Data)                  SearchData * const Data)
1093  {  {
         Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);  
1094          Data->iMinSAD = OldData->iMinSAD + 1 + block;          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1095          Data->currentMV = OldData->currentMV + 1 + block;          Data->currentMV = OldData->currentMV + 1 + block;
1096            Data->currentQMV = OldData->currentQMV + 1 + block;
1097    
1098          if (block != 0)          if(pParam->m_quarterpel) {
1099                  *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *                  Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1100                    if (block != 0) *(Data->iMinSAD) += (Data->lambda8 *
1101                                                                            d_mv_bits(      Data->currentQMV->x - Data->predMV.x,
1102                                                                                                    Data->currentQMV->y - Data->predMV.y,
1103                                                                                                    Data->iFcode) * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
1104            } else {
1105                    Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1106                    if (block != 0) *(Data->iMinSAD) += (Data->lambda8 *
1107                                                                  d_mv_bits(      Data->currentMV->x - Data->predMV.x,                                                                  d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1108                                                                                          Data->currentMV->y - Data->predMV.y,                                                                                          Data->currentMV->y - Data->predMV.y,
1109                                                                                          Data->iFcode);                                                                                                  Data->iFcode) * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
1110            }
1111    
1112          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
1113    
# Line 864  Line 1117 
1117                  Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1118    
1119                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
1120                    Data->qpel_precision = 0;
1121    
1122                  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,
1123                                  pParam->width, pParam->height, OldData->iFcode);                                  pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
   
1124                  CheckCandidate = CheckCandidate8;                  CheckCandidate = CheckCandidate8;
1125    
1126                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & PMV_EXTSEARCH8) {
1127                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1128    
1129                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1130                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1131                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1132                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1133    
1134                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);    }                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1135    
1136                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(Data);                          if(*(Data->iMinSAD) < temp_sad) {
1137                                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1138                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1139          }          }
1140                    }
1141    
1142                    if (MotionFlags & PMV_HALFPELREFINE8) {
1143                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1144    
1145                            SubpelRefine(Data); // perform halfpel refine of current best vector
1146    
1147                            if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1148                                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1149                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1150                            }
1151                    }
1152    
1153                    if(pParam->m_quarterpel) {
1154                            if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1155                                    (MotionFlags & PMV_QUARTERPELREFINE8)) {
1156                            Data->qpel_precision = 1;
1157                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1158                                    pParam->width, pParam->height, OldData->iFcode, 0);
1159                            SubpelRefine(Data);
1160                            }
1161                    }
1162            }
1163    
1164            if(pParam->m_quarterpel) {
1165                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predMV.x;
1166                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predMV.y;
1167                    pMB->qmvs[block] = *(Data->currentQMV);
1168            }
1169            else {
1170          pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;          pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1171          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1172            }
1173    
1174          pMB->mvs[block] = *(Data->currentMV);          pMB->mvs[block] = *(Data->currentMV);
1175          pMB->sad8[block] =  4 * (*Data->iMinSAD);          pMB->sad8[block] =  4 * (*Data->iMinSAD);
   
1176  }  }
1177    
1178  /* B-frames code starts here */  /* B-frames code starts here */
# Line 947  Line 1233 
1233                          const IMAGE * const pCur,                          const IMAGE * const pCur,
1234                          const int x, const int y,                          const int x, const int y,
1235                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
1236                          const uint32_t iFcode,                          const uint32_t iFcode,
1237                          const MBParam * const pParam,                          const MBParam * const pParam,
1238                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
1239                          const VECTOR * const predMV,                          const VECTOR * const predMV,
1240                          int32_t * const best_sad,                          int32_t * const best_sad,
1241                          const int32_t mode_current)                          const int32_t mode_current,
1242                            SearchData * const Data)
1243  {  {
1244    
1245          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1246    
1247          int i, iDirection, mask;          int i, iDirection, mask;
1248          VECTOR currentMV, pmv[7];          VECTOR pmv[7];
1249          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1250          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
1251          SearchData Data;          Data->iFcode = iFcode;
1252            Data->qpel_precision = 0;
1253          Data.iMinSAD = &iMinSAD;  
1254          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->Ref = pRef + (x + y * iEdgedWidth) * 16;
1255          Data.iEdgedWidth = iEdgedWidth;          Data->RefH = pRefH + (x + y * iEdgedWidth) * 16;
1256          Data.currentMV = &currentMV;          Data->RefV = pRefV + (x + y * iEdgedWidth) * 16;
1257          Data.iMinSAD = &iMinSAD;          Data->RefHV = pRefHV + (x + y * iEdgedWidth) * 16;
         Data.Ref = pRef + (x + y * iEdgedWidth) * 16;  
         Data.RefH = pRefH + (x + y * iEdgedWidth) * 16;  
         Data.RefV = pRefV + (x + y * iEdgedWidth) * 16;  
         Data.RefHV = pRefHV + (x + y * iEdgedWidth) * 16;  
   
         Data.iQuant = iQuant;  
         Data.iFcode = iFcode;  
         Data.predMV = *predMV;  
   
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,  
                                 pParam->width, pParam->height, iFcode);  
   
         if (!(MotionFlags & PMV_HALFPEL16)) {  
                 Data.min_dx = EVEN(Data.min_dx);  
                 Data.max_dx = EVEN(Data.max_dx);  
                 Data.min_dy = EVEN(Data.min_dy);  
                 Data.max_dy = EVEN(Data.max_dy); } // no-halpel and b-frames. do we need it?  
1258    
1259            Data->predMV = *predMV;
1260    
1261          pmv[0] = Data.predMV;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1262          PreparePredictionsBF(pmv, x, y, pParam->mb_width,                                  pParam->width, pParam->height, iFcode, pParam->m_quarterpel);
                                         pMB, mode_current);  
1263    
1264          currentMV.x = currentMV.y = 0;          pmv[0] = Data->predMV;
1265            if (Data->qpel) { pmv[0].x /= 2; pmv[0].y /= 2; }
1266            PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
1267    
1268            Data->currentMV->x = Data->currentMV->y = 0;
1269          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1270    
1271  // main loop. checking all predictions  // main loop. checking all predictions
1272          for (i = 0; i < 8; i++) {          for (i = 0; i < 8; i++) {
1273                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1274                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1275          }          }
1276    
1277          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1008  Line 1280 
1280                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1281                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1282    
1283          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1284    
1285            SubpelRefine(Data);
1286    
1287          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (Data->qpel) {
1288                    Data->currentQMV->x = 2*Data->currentMV->x;
1289                    Data->currentQMV->y = 2*Data->currentMV->y;
1290                    Data->qpel_precision = 1;
1291                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1292                                            pParam->width, pParam->height, iFcode, 0);
1293                    SubpelRefine(Data);
1294            }
1295    
1296  // three bits are needed to code backward mode. four for forward  // three bits are needed to code backward mode. four for forward
1297  // we treat the bits just like they were vector's  // we treat the bits just like they were vector's
1298          if (mode_current == MODE_FORWARD) iMinSAD +=  4 * lambda_vec16[iQuant];          if (mode_current == MODE_FORWARD) *Data->iMinSAD +=  4 * Data->lambda16;
1299          else iMinSAD +=  3 * lambda_vec16[iQuant];          else *Data->iMinSAD +=  3 * Data->lambda16;
   
1300    
1301          if (iMinSAD < *best_sad) {          if (*Data->iMinSAD < *best_sad) {
1302                  *best_sad = iMinSAD;                  *best_sad = *Data->iMinSAD;
1303                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1304                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  if (Data->qpel) {
1305                  pMB->pmvs[0].y = currentMV.y - predMV->y;                          pMB->pmvs[0].x = Data->currentQMV->x - predMV->x;
1306                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                          pMB->pmvs[0].y = Data->currentQMV->y - predMV->y;
1307                  else pMB->b_mvs[0] = currentMV;                          if (mode_current == MODE_FORWARD)
1308                                    pMB->qmvs[0] = *Data->currentQMV;
1309                            else
1310                                    pMB->b_qmvs[0] = *Data->currentQMV;
1311                    } else {
1312                            pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1313                            pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1314                    }
1315                    if (mode_current == MODE_FORWARD)
1316                            pMB->mvs[0] = *(Data->currentMV+2) = *Data->currentMV;
1317                    else
1318                            pMB->b_mvs[0] = *(Data->currentMV+1) = *Data->currentMV; //we store currmv for interpolate search
1319    
1320          }          }
1321    
1322  }  }
# Line 1041  Line 1333 
1333                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1334                                  const int x, const int y,                                  const int x, const int y,
1335                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1336                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1337                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1338                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1339                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1340                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1341                                    SearchData * const Data)
1342    
1343  {  {
1344          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
         int32_t iMinSAD = 266*4096, skip_sad;  
1345          int k;          int k;
1346          VECTOR currentMV;  
1347          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
         SearchData Data;  
1348    
1349          Data.iMinSAD = &iMinSAD;          *Data->iMinSAD = 256*4096;
         Data.Cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;  
         Data.iEdgedWidth = iEdgedWidth;  
         Data.currentMV = &currentMV;  
         Data.iQuant = iQuant;  
         Data.referencemv = b_mb->mvs;  
1350    
1351          Data.Ref= f_Ref->y + (x + iEdgedWidth*y) * 16;          Data->Ref = f_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1352          Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;          Data->RefH = f_RefH + (x + Data->iEdgedWidth*y) * 16;
1353          Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;          Data->RefV = f_RefV + (x + Data->iEdgedWidth*y) * 16;
1354          Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = f_RefHV + (x + Data->iEdgedWidth*y) * 16;
1355          Data.bRef = b_Ref->y + (x + iEdgedWidth*y) * 16;          Data->bRef = b_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1356          Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;          Data->bRefH = b_RefH + (x + Data->iEdgedWidth*y) * 16;
1357          Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;          Data->bRefV = b_RefV + (x + Data->iEdgedWidth*y) * 16;
1358          Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;          Data->bRefHV = b_RefHV + (x + Data->iEdgedWidth*y) * 16;
1359  /*  
1360  //What we do here is a complicated version of CheckCandidateDirect(0,0);          Data->max_dx = 2 * pParam->width - 2 * (x) * 16;
1361  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;
1362            Data->min_dx = -(2 * 16 + 2 * (x) * 16);
1363  */          Data->min_dy = -(2 * 16 + 2 * (y) * 16);
1364          Data.max_dx = 2 * pParam->width - 2 * (x) * 16;          if (Data->qpel) { //we measure in qpixels
1365          Data.max_dy = 2 * pParam->height - 2 * (y) * 16;                  Data->max_dx *= 2;
1366          Data.min_dx = -(2 * 16 + 2 * (x) * 16);                  Data->max_dy *= 2;
1367          Data.min_dy = -(2 * 16 + 2 * (y) * 16);                  Data->min_dx *= 2;
1368                    Data->min_dy *= 2;
1369                    Data->referencemv = b_mb->qmvs;
1370            } else Data->referencemv = b_mb->mvs;
1371            Data->qpel_precision = 0; // it'm a trick. it's 1 not 0, but we need 0 here
1372    
1373          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1374                  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);
1375                  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;
1376                  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);
1377                  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;
1378    
1379                  if (( pMB->mvs[k].x > Data.max_dx ) || ( pMB->mvs[k].x < Data.min_dx )                  if ( ( pMB->b_mvs[k].x > Data->max_dx ) || ( pMB->b_mvs[k].x < Data->min_dx )
1380                          || ( pMB->mvs[k].y > Data.max_dy ) || ( pMB->mvs[k].y < Data.min_dy )                          || ( pMB->b_mvs[k].y > Data->max_dy ) || ( pMB->b_mvs[k].y < Data->min_dy )) {
                         || ( pMB->b_mvs[k].x > Data.max_dx ) || ( pMB->b_mvs[k].x < Data.min_dx )  
                         || ( pMB->b_mvs[k].y > Data.max_dy ) || ( pMB->b_mvs[k].y < Data.min_dy )) {  
1381    
1382                          *best_sad = 256*4096; // in that case, we won't use direct mode                          *best_sad = 256*4096; // in that case, we won't use direct mode
1383                          pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"                          pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
# Line 1100  Line 1387 
1387                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1388                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1389                          pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];                          pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];
1390                          Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1391                          Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1392                          break;                          break;
1393                  }                  }
1394          }          }
1395    
1396          if (b_mb->mode == MODE_INTER4V)  
1397                  CheckCandidate = CheckCandidateDirect;          if (b_mb->mode == MODE_INTER4V) CheckCandidate = CheckCandidateDirect;
1398          else CheckCandidate = CheckCandidateDirectno4v;          else CheckCandidate = CheckCandidateDirectno4v;
1399    
1400          (*CheckCandidate)(0, 0, 255, &k, &Data);          (*CheckCandidate)(0, 0, 255, &k, Data);
1401    
1402  // skip decision  // skip decision
1403          if (iMinSAD - 2 * lambda_vec16[iQuant] < (int32_t)iQuant * SKIP_THRESH_B) {          if (*Data->iMinSAD < pMB->quant * SKIP_THRESH_B) {
1404                  //checking chroma. everything copied from MC                  //possible skip - checking chroma. everything copied from MC
1405                  //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
1406                  int sum, dx, dy, b_dx, b_dy;                  int sum, dx, dy, b_dx, b_dy;
1407    
1408                    if (Data->qpel) {
1409                            sum = pMB->mvs[0].y/2 + pMB->mvs[1].y/2 + pMB->mvs[2].y/2 + pMB->mvs[3].y/2;
1410                            dy = (sum >> 3) + roundtab_76[sum & 0xf];
1411                            sum = pMB->mvs[0].x/2 + pMB->mvs[1].x/2 + pMB->mvs[2].x/2 + pMB->mvs[3].x/2;
1412                            dx = (sum >> 3) + roundtab_76[sum & 0xf];
1413    
1414                            sum = pMB->b_mvs[0].y/2 + pMB->b_mvs[1].y/2 + pMB->b_mvs[2].y/2 + pMB->b_mvs[3].y/2;
1415                            b_dy = (sum >> 3) + roundtab_76[sum & 0xf];
1416                            sum = pMB->b_mvs[0].x/2 + pMB->b_mvs[1].x/2 + pMB->b_mvs[2].x/2 + pMB->b_mvs[3].x/2;
1417                            b_dx = (sum >> 3) + roundtab_76[sum & 0xf];
1418    
1419                    } else {
1420                  sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;                  sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1421                  dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));                  dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
   
1422                  sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;                  sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1423                  dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));                  dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1424    
1425                  sum = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;                  sum = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;
1426                  b_dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));                  b_dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
   
1427                  sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;                  sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;
1428                  b_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));                  b_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1429                    }
1430                    sum = sad8bi(pCur->u + 8*x + 8*y*(Data->iEdgedWidth/2),
1431                                            f_Ref->u + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1432                                            b_Ref->u + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1433                                            Data->iEdgedWidth/2);
1434                    sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1435                                            f_Ref->v + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1436                                            b_Ref->v + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1437                                            Data->iEdgedWidth/2);
1438    
1439                  sum = sad8bi(pCur->u + 8*x + 8*y*(iEdgedWidth/2),                  if (sum < MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) {
                                         f_Ref->u + (y*8 + dy/2) * (iEdgedWidth/2) + x*8 + dx/2,  
                                         b_Ref->u + (y*8 + b_dy/2) * (iEdgedWidth/2) + x*8 + b_dx/2,  
                                         iEdgedWidth/2);  
                 sum += sad8bi(pCur->v + 8*x + 8*y*(iEdgedWidth/2),  
                                         f_Ref->v + (y*8 + dy/2) * (iEdgedWidth/2) + x*8 + dx/2,  
                                         b_Ref->v + (y*8 + b_dy/2) * (iEdgedWidth/2) + x*8 + b_dx/2,  
                                         iEdgedWidth/2);  
   
                 if ((uint32_t) sum < MAX_CHROMA_SAD_FOR_SKIP * Data.iQuant) {  
1440                          pMB->mode = MODE_DIRECT_NONE_MV;                          pMB->mode = MODE_DIRECT_NONE_MV;
1441                          return iMinSAD;                          return *Data->iMinSAD;
1442                  }                  }
1443          }          }
1444    
1445          skip_sad = iMinSAD;          skip_sad = *Data->iMinSAD;
1446    
1447  //  DIRECT MODE DELTA VECTOR SEARCH.  //  DIRECT MODE DELTA VECTOR SEARCH.
1448  //      This has to be made more effective, but at the moment I'm happy it's running at all  //      This has to be made more effective, but at the moment I'm happy it's running at all
# Line 1154  Line 1451 
1451                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1452                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1453    
1454          (*MainSearchPtr)(0, 0, &Data, 255);          (*MainSearchPtr)(0, 0, Data, 255);
1455    
1456          HalfpelRefine(&Data);          SubpelRefine(Data);
1457    
1458          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 * Data->lambda16; // one bit is needed to code direct mode
1459          *best_sad = iMinSAD;          *best_sad = *Data->iMinSAD;
1460    
1461          if (b_mb->mode == MODE_INTER4V)  //      if (b_mb->mode == MODE_INTER4V)
1462                  pMB->mode = MODE_DIRECT;                  pMB->mode = MODE_DIRECT;
1463          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation  //      else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1464    
1465          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1466    
1467          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1468                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1469                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = (     (Data->currentMV->x == 0)
1470                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1471                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          :pMB->mvs[k].x - Data->referencemv[k].x);
1472                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1473                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1474                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1475                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1476                    if (Data->qpel) {
1477                            pMB->qmvs[k].x = pMB->mvs[k].x; pMB->mvs[k].x /= 2;
1478                            pMB->b_qmvs[k].x = pMB->b_mvs[k].x; pMB->b_mvs[k].x /= 2;
1479                            pMB->qmvs[k].y = pMB->mvs[k].y; pMB->mvs[k].y /= 2;
1480                            pMB->b_qmvs[k].y = pMB->b_mvs[k].y; pMB->b_mvs[k].y /= 2;
1481                    }
1482    
1483                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1484                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1485                          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];
1486                            pMB->qmvs[3] = pMB->qmvs[2] = pMB->qmvs[1] = pMB->qmvs[0];
1487                            pMB->b_qmvs[3] = pMB->b_qmvs[2] = pMB->b_qmvs[1] = pMB->b_qmvs[0];
1488                          break;                          break;
1489                  }                  }
1490          }          }
1491          return 0;//skip_sad;          return skip_sad;
1492  }  }
1493    
1494    
1495  static __inline void  static __inline void
1496  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const uint8_t * const f_Ref,
1497                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
# Line 1199  Line 1506 
1506                                  const uint32_t fcode,                                  const uint32_t fcode,
1507                                  const uint32_t bcode,                                  const uint32_t bcode,
1508                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1509                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1510                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1511                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1512                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1513                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1514                                    SearchData * const fData)
1515    
1516  {  {
 /* 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". */  
1517    
1518          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
   
1519          int iDirection, i, j;          int iDirection, i, j;
1520          int32_t iMinSAD = 256*4096;          SearchData bData;
         VECTOR currentMV[3];  
         SearchData fData, bData;  
   
         fData.iMinSAD = bData.iMinSAD = &iMinSAD;  
1521    
1522          fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          *(bData.iMinSAD = fData->iMinSAD) = 4096*256;
1523          fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;          bData.Cur = fData->Cur;
1524          fData.currentMV = currentMV; bData.currentMV = currentMV + 1;          fData->iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;
1525          fData.iQuant = bData.iQuant = iQuant;          bData.currentMV = fData->currentMV + 1; bData.currentQMV = fData->currentQMV + 1;
1526          fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;          bData.lambda16 = fData->lambda16;
1527            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1528          bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  
1529          bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;          bData.bRef = fData->Ref = f_Ref + (x + y * iEdgedWidth) * 16;
1530          bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;          bData.bRefH = fData->RefH = f_RefH + (x + y * iEdgedWidth) * 16;
1531          bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;          bData.bRefV = fData->RefV = f_RefV + (x + y * iEdgedWidth) * 16;
1532          bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;          bData.bRefHV = fData->RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;
1533          bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;          bData.Ref = fData->bRef = b_Ref + (x + y * iEdgedWidth) * 16;
1534          bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;          bData.RefH = fData->bRefH = b_RefH + (x + y * iEdgedWidth) * 16;
1535          bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;          bData.RefV = fData->bRefV = b_RefV + (x + y * iEdgedWidth) * 16;
1536            bData.RefHV = fData->bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;
1537          bData.bpredMV = fData.predMV = *f_predMV;          bData.RefQ = fData->RefQ;
1538          fData.bpredMV = bData.predMV = *b_predMV;          fData->qpel_precision = bData.qpel_precision = 0;
1539            bData.rounding = 0; bData.qpel = fData->qpel;
1540          currentMV[0] = pMB->mvs[0];  
1541          currentMV[1] = pMB->b_mvs[0];          bData.bpredMV = fData->predMV = *f_predMV;
1542          get_range(&fData.min_dx, &fData.max_dx, &fData.min_dy, &fData.max_dy, x, y, 16, pParam->width, pParam->height, fcode);          fData->bpredMV = bData.predMV = *b_predMV;
1543          get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode);  
1544            fData->currentMV[0] = fData->currentMV[2];
1545          if (currentMV[0].x > fData.max_dx) currentMV[0].x = fData.max_dx;          get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, pParam->m_quarterpel);
1546          if (currentMV[0].x < fData.min_dx) currentMV[0].x = fData.min_dy;          get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, pParam->m_quarterpel);
1547          if (currentMV[0].y > fData.max_dy) currentMV[0].y = fData.max_dx;  
1548          if (currentMV[0].y > fData.min_dy) currentMV[0].y = fData.min_dy;          if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1549            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dy;
1550          if (currentMV[1].x > bData.max_dx) currentMV[1].x = bData.max_dx;          if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dx;
1551          if (currentMV[1].x < bData.min_dx) currentMV[1].x = bData.min_dy;          if (fData->currentMV[0].y > fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1552          if (currentMV[1].y > bData.max_dy) currentMV[1].y = bData.max_dx;  
1553          if (currentMV[1].y > bData.min_dy) currentMV[1].y = bData.min_dy;          if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1554            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dy;
1555            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dx;
1556            if (fData->currentMV[1].y > bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1557    
1558          CheckCandidateInt(currentMV[0].x, currentMV[0].y, 255, &iDirection, &fData);          CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
1559    
1560  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)
1561    
1562          do {          do {
1563                  iDirection = 255;                  iDirection = 255;
1564                  // forward MV moves                  // forward MV moves
1565                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
1566    
1567                  CheckCandidateInt(i + 1, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1568                  CheckCandidateInt(i, j + 1, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1569                  CheckCandidateInt(i - 1, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1570                  CheckCandidateInt(i, j - 1, 0, &iDirection, &fData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
1571    
1572                  // backward MV moves                  // backward MV moves
1573                  i = currentMV[1].x; j = currentMV[1].y;                  i = fData->currentMV[1].x; j = fData->currentMV[1].y;
1574                  currentMV[2] = currentMV[0];                  fData->currentMV[2] = fData->currentMV[0];
   
1575                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1576                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1577                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
# Line 1279  Line 1579 
1579    
1580          } while (!(iDirection));          } while (!(iDirection));
1581    
1582  // two bits are needed to code interpolate mode. we treat the bits just like they were vector's          *fData->iMinSAD +=  2 * fData->lambda16; // two bits are needed to code interpolate mode.
         iMinSAD +=  2 * lambda_vec16[iQuant];  
         if (iMinSAD < *best_sad) {  
                 *best_sad = iMinSAD;  
                 pMB->mvs[0] = currentMV[0];  
                 pMB->b_mvs[0] = currentMV[1];  
                 pMB->mode = MODE_INTERPOLATE;  
1583    
1584            if (fData->qpel) {
1585                    fData->qpel_precision = bData.qpel_precision = 1;
1586                    get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, 0);
1587                    get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, 0);
1588                    fData->currentQMV[2].x = fData->currentQMV[0].x = 2 * fData->currentMV[0].x;
1589                    fData->currentQMV[2].y = fData->currentQMV[0].y = 2 * fData->currentMV[0].y;
1590                    fData->currentQMV[1].x = 2 * fData->currentMV[1].x;
1591                    fData->currentQMV[1].y = 2 * fData->currentMV[1].y;
1592                    SubpelRefine(fData);
1593                    fData->currentQMV[2] = fData->currentQMV[0];
1594                    SubpelRefine(&bData);
1595            }
1596    
1597            if (*fData->iMinSAD < *best_sad) {
1598                    *best_sad = *fData->iMinSAD;
1599                    pMB->mvs[0] = fData->currentMV[0];
1600                    pMB->b_mvs[0] = fData->currentMV[1];
1601                    pMB->mode = MODE_INTERPOLATE;
1602                    if (fData->qpel) {
1603                            pMB->qmvs[0] = fData->currentQMV[0];
1604                            pMB->b_qmvs[0] = fData->currentQMV[1];
1605                            pMB->pmvs[1].x = pMB->qmvs[0].x - f_predMV->x;
1606                            pMB->pmvs[1].y = pMB->qmvs[0].y - f_predMV->y;
1607                            pMB->pmvs[0].x = pMB->b_qmvs[0].x - b_predMV->x;
1608                            pMB->pmvs[0].y = pMB->b_qmvs[0].y - b_predMV->y;
1609                    } else {
1610                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;
1611                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;
1612                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;
1613                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;
1614          }          }
1615  }  }
1616    }
1617    
1618  void  void
1619  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
# Line 1306  Line 1627 
1627                                           const IMAGE * const f_refV,                                           const IMAGE * const f_refV,
1628                                           const IMAGE * const f_refHV,                                           const IMAGE * const f_refHV,
1629                                           // backward (future) reference                                           // backward (future) reference
1630                                           const MACROBLOCK * const b_mbs,                                           const FRAMEINFO * const b_reference,
1631                                           const IMAGE * const b_ref,                                           const IMAGE * const b_ref,
1632                                           const IMAGE * const b_refH,                                           const IMAGE * const b_refH,
1633                                           const IMAGE * const b_refV,                                           const IMAGE * const b_refV,
# Line 1316  Line 1637 
1637          int32_t best_sad, skip_sad;          int32_t best_sad, skip_sad;
1638          int f_count = 0, b_count = 0, i_count = 0, d_count = 0, n_count = 0;          int f_count = 0, b_count = 0, i_count = 0, d_count = 0, n_count = 0;
1639          static const VECTOR zeroMV={0,0};          static const VECTOR zeroMV={0,0};
1640            const MACROBLOCK * const b_mbs = b_reference->mbs;
1641    
1642          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
1643    
1644          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1645          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
1646            uint8_t * qimage;
1647    
1648          // note: i==horizontal, j==vertical  // some pre-inintialized data for the rest of the search
1649    
1650            SearchData Data;
1651            int32_t iMinSAD;
1652            VECTOR currentMV[3];
1653            VECTOR currentQMV[3];
1654            Data.iEdgedWidth = pParam->edged_width;
1655            Data.currentMV = currentMV; Data.currentQMV = currentQMV;
1656            Data.iMinSAD = &iMinSAD;
1657            Data.lambda16 = lambda_vec16[frame->quant];
1658            Data.qpel = pParam->m_quarterpel;
1659            Data.rounding = 0;
1660    
1661            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
1662                    return; // allocate some mem for qpel interpolated blocks
1663                                      // somehow this is dirty since I think we shouldn't use malloc outside
1664                                      // encoder_create() - so please fix me!
1665            Data.RefQ = qimage;
1666    
1667            // note: i==horizontal, j==vertical
1668          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
1669    
1670                  f_predMV = b_predMV = zeroMV;   /* prediction is reset at left boundary */                  f_predMV = b_predMV = zeroMV;   /* prediction is reset at left boundary */
# Line 1332  Line 1673 
1673                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;
1674                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;
1675    
1676  /* special case, if collocated block is SKIPed: encoding is forward (0,0), cpb=0 without further ado */  /* special case, if collocated block is SKIPed in P-VOP: encoding is forward (0,0), cpb=0 without further ado */
1677                            if (b_reference->coding_type != S_VOP)
1678                          if (b_mb->mode == MODE_NOT_CODED) {                          if (b_mb->mode == MODE_NOT_CODED) {
1679                                  pMB->mode = MODE_NOT_CODED;                                  pMB->mode = MODE_NOT_CODED;
1680                                  continue;                                  continue;
1681                          }                          }
1682    
1683                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
1684                            pMB->quant = frame->quant;
1685    
1686  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
1687          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
   
1688                          skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,                          skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
1689                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,
1690                                                                          &frame->image,                                                                          &frame->image,
1691                                                                          i, j,                                                                          i, j,
1692                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
1693                                                                          TRB, TRD,                                                                          TRB, TRD,
1694                                                                          pParam,                                                                          pParam,
1695                                                                          pMB, b_mb,                                                                          pMB, b_mb,
1696                                                                          &best_sad);                                                                          &best_sad,
1697                                                                            &Data);
1698    
1699                          if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                          if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1700    
 //                      best_sad = 256*4096; //uncomment to disable Directsearch.  
 //      To disable any other mode, just comment the function call  
   
1701                          // forward search                          // forward search
1702                          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,
1703                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1704                                                  frame->motion_flags,                                                  frame->motion_flags,
1705                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
1706                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
1707                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
1708    
1709                          // backward search                          // backward search
1710                          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,
1711                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1712                                                  frame->motion_flags,                                                  frame->motion_flags,
1713                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
1714                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
1715                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
1716    
1717                          // 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
1718    
# Line 1381  Line 1722 
1722                                                  i, j,                                                  i, j,
1723                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
1724                                                  frame->motion_flags,                                                  frame->motion_flags,
1725                                                  frame->quant, pParam,                                                  pParam,
1726                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
1727                                                  pMB, &best_sad);                                                  pMB, &best_sad,
1728                                                    &Data);
1729    
1730                          switch (pMB->mode) {                          switch (pMB->mode) {
1731                                  case MODE_FORWARD:                                  case MODE_FORWARD:
1732                                          f_count++;                                          f_count++;
1733                                          f_predMV = pMB->mvs[0];                                          if (pParam->m_quarterpel) f_predMV = pMB->qmvs[0];
1734                                            else f_predMV = pMB->mvs[0];
1735                                          break;                                          break;
1736                                  case MODE_BACKWARD:                                  case MODE_BACKWARD:
1737                                          b_count++;                                          b_count++;
1738                                          b_predMV = pMB->b_mvs[0];                                          if (pParam->m_quarterpel) b_predMV = pMB->b_qmvs[0];
1739                                            else b_predMV = pMB->b_mvs[0];
1740                                          break;                                          break;
1741                                  case MODE_INTERPOLATE:                                  case MODE_INTERPOLATE:
1742                                          i_count++;                                          i_count++;
1743                                            if (pParam->m_quarterpel) {
1744                                                    f_predMV = pMB->qmvs[0];
1745                                                    b_predMV = pMB->b_qmvs[0];
1746                                            } else {
1747                                          f_predMV = pMB->mvs[0];                                          f_predMV = pMB->mvs[0];
1748                                          b_predMV = pMB->b_mvs[0];                                          b_predMV = pMB->b_mvs[0];
1749                                            }
1750                                          break;                                          break;
1751                                  case MODE_DIRECT:                                  case MODE_DIRECT:
1752                                  case MODE_DIRECT_NO4V:                                  case MODE_DIRECT_NO4V:
# Line 1408  Line 1757 
1757                          }                          }
1758                  }                  }
1759          }          }
1760            free(qimage);
 //      fprintf(debug,"B-Stat: F: %04d   B: %04d   I: %04d  D: %04d, N: %04d\n",  
 //                              f_count,b_count,i_count,d_count,n_count);  
   
1761  }  }
1762    
1763  /* Hinted ME starts here */  /* Hinted ME starts here */
1764    
 static __inline void  
 Search8hinted(  const SearchData * const OldData,  
                                 const int x, const int y,  
                                 const uint32_t MotionFlags,  
                                 const MBParam * const pParam,  
                                 MACROBLOCK * const pMB,  
                                 const MACROBLOCK * const pMBs,  
                                 const int block)  
 {  
         SearchData Data;  
         MainSearchFunc *MainSearchPtr;  
   
         Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);  
         Data.iMinSAD = OldData->iMinSAD + 1 + block;  
         Data.currentMV = OldData->currentMV+1+block;  
         Data.iFcode = OldData->iFcode;  
         Data.iQuant = OldData->iQuant;  
   
         Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));  
         Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));  
         Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));  
         Data.RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));  
         Data.iEdgedWidth = pParam->edged_width;  
         Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));  
   
         CheckCandidate = CheckCandidate8;  
   
         if (block != 0)  
                 *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *  
                                                                 d_mv_bits(      Data.currentMV->x - Data.predMV.x,  
                                                                                         Data.currentMV->y - Data.predMV.y,  
                                                                                         Data.iFcode);  
   
   
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,  
                                 pParam->width, pParam->height, OldData->iFcode);  
   
         if (pMB->mode == MODE_INTER4V) {  
                 int dummy;  
                 CheckCandidate8(pMB->mvs[block].x, pMB->mvs[block].y, 0, &dummy, &Data); }  
   
         if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;  
                 else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;  
                         else MainSearchPtr = DiamondSearch;  
   
         (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);  
   
         if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);  
   
         pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;  
         pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;  
         pMB->mvs[block] = *(Data.currentMV);  
         pMB->sad8[block] =  4 * (*(Data.iMinSAD));  
 }  
   
   
1765  static void  static void
1766  SearchPhinted ( const uint8_t * const pRef,  SearchPhinted ( const IMAGE * const pRef,
1767                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
1768                                  const uint8_t * const pRefV,                                  const uint8_t * const pRefV,
1769                                  const uint8_t * const pRefHV,                                  const uint8_t * const pRefHV,
# Line 1482  Line 1772 
1772                                  const int y,                                  const int y,
1773                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1774                                  const uint32_t iQuant,                                  const uint32_t iQuant,
                                 const uint32_t iFcode,  
1775                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1776                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1777                                  int inter4v,                                  int inter4v,
1778                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
1779                                    SearchData * const Data)
1780  {  {
1781    
1782          const int32_t iEdgedWidth = pParam->edged_width;          int i, t;
   
         int i;  
         VECTOR currentMV[5];  
         int32_t iMinSAD[5];  
         int32_t temp[5];  
1783          MainSearchFunc * MainSearchPtr;          MainSearchFunc * MainSearchPtr;
         SearchData Data;  
1784    
1785          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,
1786          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
                                 pParam->width, pParam->height, iFcode);  
1787    
1788          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
1789          Data.iEdgedWidth = iEdgedWidth;          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1790          Data.currentMV = currentMV;          Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1791          Data.iMinSAD = iMinSAD;  
1792          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16;
1793          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
1794          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
1795          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
1796          Data.temp = temp;          Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1797          Data.iQuant = iQuant;          Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1798          Data.iFcode = iFcode;          Data->qpel_precision = 0;
1799    
1800          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
1801                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
1802                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
1803                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
1804                  Data.max_dy = EVEN(Data.max_dy);                  Data->max_dy = EVEN(Data->max_dy);
1805          }          }
1806            if (pParam->m_quarterpel) Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1807            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1808    
1809          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;          for(i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
1810    
1811          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
1812    
1813          if (inter4v)          if (inter4v || Data->chroma) CheckCandidate = CheckCandidate16;
                 CheckCandidate = CheckCandidate16;  
1814          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
1815    
   
1816          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);
1817          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);
1818          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
1819          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;
1820          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;
1821          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;
1822    
1823          CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);          (*CheckCandidate)(pMB->mvs[0].x, pMB->mvs[0].y, 0, &t, Data);
1824    
1825          if (pMB->mode == MODE_INTER4V)          if (pMB->mode == MODE_INTER4V)
1826                  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
1827                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);
1828                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);
1829                          if (!(make_mask(pMB->mvs, i)))                          if (!(make_mask(pMB->mvs, i)))
1830                                  CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);                                  (*CheckCandidate)(pMB->mvs[i].x, pMB->mvs[i].y, 0, &t, Data);
1831                  }                  }
1832    
1833          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1553  Line 1836 
1836                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1837                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1838    
1839          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1840    
1841          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (MotionFlags & PMV_HALFPELREFINE16) SubpelRefine(Data);
1842    
1843          if (inter4v)          for(i = 0; i < 5; i++) {
1844                  for(i = 0; i < 4; i++)                  Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1845                          Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                  Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1846            }
1847    
1848            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1849                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1850                                    pParam->width, pParam->height, Data->iFcode, 0);
1851                    Data->qpel_precision = 1;
1852                    SubpelRefine(Data);
1853            }
1854    
1855            if (inter4v) {
1856                    SearchData Data8;
1857                    Data8.iFcode = Data->iFcode;
1858                    Data8.lambda8 = Data->lambda8;
1859                    Data8.iEdgedWidth = Data->iEdgedWidth;
1860                    Data8.RefQ = Data->RefQ;
1861                    Data8.qpel = Data->qpel;
1862                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1863                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1864                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1865                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1866    
1867                    if (Data->chroma) {
1868                            int sumx, sumy, dx, dy;
1869    
1870                            if(pParam->m_quarterpel) {
1871                                    sumx= pMB->qmvs[0].x/2 + pMB->qmvs[1].x/2 + pMB->qmvs[2].x/2 + pMB->qmvs[3].x/2;
1872                                    sumy = pMB->qmvs[0].y/2 + pMB->qmvs[1].y/2 + pMB->qmvs[2].y/2 + pMB->qmvs[3].y/2;
1873                            } else {
1874                                    sumx = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1875                                    sumy = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1876                            }
1877                            dx = (sumx >> 3) + roundtab_76[sumx & 0xf];
1878                            dy = (sumy >> 3) + roundtab_76[sumy & 0xf];
1879    
1880                            Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);
1881                    }
1882            }
1883    
1884          if (!(inter4v) ||          if (!(inter4v) ||
1885                  (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] +
1886                                                            Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1887  // INTER MODE  // INTER MODE
   
1888                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1889                  pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1890                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1891    
1892                    pMB->qmvs[0] = pMB->qmvs[1]
1893                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1894    
1895                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1896                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1897    
1898                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1899                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predMV.x;
1900                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predMV.y;
1901          } else {          } else {
1902  // INTER4V MODE; all other things are already set in Search8hinted                          pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1903                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1904                    }
1905            } else {
1906    // INTER4V MODE; all other things are already set in Search8
1907                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1908                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3]
1909                                                    + Data->iMinSAD[4] + IMV16X16 * iQuant;
1910          }          }
1911    
1912  }  }
# Line 1595  Line 1924 
1924          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
1925    
1926          uint32_t x, y;          uint32_t x, y;
1927            uint8_t * qimage;
1928            int32_t temp[5], quant = current->quant;
1929            int32_t iMinSAD[5];
1930            VECTOR currentMV[5], currentQMV[5];
1931            SearchData Data;
1932            Data.iEdgedWidth = pParam->edged_width;
1933            Data.currentMV = currentMV;
1934            Data.currentQMV = currentQMV;
1935            Data.iMinSAD = iMinSAD;
1936            Data.temp = temp;
1937            Data.iFcode = current->fcode;
1938            Data.rounding = pParam->m_rounding_type;
1939            Data.qpel = pParam->m_quarterpel;
1940            Data.chroma = current->global_flags & XVID_ME_COLOUR;
1941    
1942            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
1943                    return; // allocate some mem for qpel interpolated blocks
1944                                      // somehow this is dirty since I think we shouldn't use malloc outside
1945                                      // encoder_create() - so please fix me!
1946    
1947            Data.RefQ = qimage;
1948    
1949          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
1950    
# Line 1609  Line 1959 
1959                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
1960                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
1961                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant; }
1962                            else {
1963                                    if (pMB->dquant != NO_CHANGE) {
1964                                            quant += DQtab[pMB->dquant];
1965                                            if (quant > 31) quant = 31;
1966                                            else if (quant < 1) quant = 1;
1967                                    }
1968                                    pMB->quant = quant;
1969                            }
1970    
1971                          SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchPhinted(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
1972                                                          y, current->motion_flags, pMB->quant,                                                          y, current->motion_flags, pMB->quant,
1973                                                          current->fcode, pParam, pMBs,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
1974                                                          current->global_flags & XVID_INTER4V, pMB);                                                          &Data);
1975    
1976                  }                  }
1977          }          }
1978            free(qimage);
1979  }  }
1980    
1981  static __inline int  static __inline int
# Line 1624  Line 1983 
1983                                  const uint8_t * const pCur,                                  const uint8_t * const pCur,
1984                                  const int x,                                  const int x,
1985                                  const int y,                                  const int y,
                                 const uint32_t iFcode,  
1986                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1987                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1988                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
1989                                    SearchData * const Data)
1990  {  {
1991    
1992          const int32_t iEdgedWidth = pParam->edged_width;          int i = 255, mask;
1993          int i, mask;          VECTOR pmv[3];
1994          VECTOR currentMV, pmv[3];          *(Data->iMinSAD) = MV_MAX_ERROR;
1995          int32_t iMinSAD = MV_MAX_ERROR;  
1996          SearchData Data;          //median is only used as prediction. it doesn't have to be real
1997            if (x == 1 && y == 1) Data->predMV.x = Data->predMV.y = 0;
1998          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          else
1999          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,                  if (x == 1) //left macroblock does not have any vector now
2000                                  pParam->width, pParam->height, iFcode);                          Data->predMV = (pMB - pParam->mb_width)->mvs[0]; // top instead of median
2001                    else if (y == 1) // top macroblock don't have it's vector
2002                            Data->predMV = (pMB - 1)->mvs[0]; // left instead of median
2003                            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); //else median
2004    
2005          Data.Cur = pCur + (x + y * iEdgedWidth) * 16;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2006          Data.iEdgedWidth = iEdgedWidth;                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
         Data.currentMV = &currentMV;  
         Data.iMinSAD = &iMinSAD;  
         Data.Ref = pRef + (x + iEdgedWidth*y)*16;  
         Data.iQuant = 2;  
         Data.iFcode = iFcode;  
2007    
2008          CheckCandidate = CheckCandidate16no4vI;          Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
2009            Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
2010    
2011          pmv[1].x = EVEN(pMB->mvs[0].x);          pmv[1].x = EVEN(pMB->mvs[0].x);
2012          pmv[1].y = EVEN(pMB->mvs[0].y);          pmv[1].y = EVEN(pMB->mvs[0].y);
2013          pmv[0].x = EVEN(Data.predMV.x);          pmv[2].x = EVEN(Data->predMV.x);
2014          pmv[0].y = EVEN(Data.predMV.y);          pmv[2].y = EVEN(Data->predMV.y);
2015          pmv[2].x = pmv[2].y = 0;          pmv[0].x = pmv[0].y = 0;
2016    
2017            (*CheckCandidate)(0, 0, 255, &i, Data);
2018    
2019    //early skip for 0,0
2020            if (*Data->iMinSAD < MAX_SAD00_FOR_SKIP * 4) {
2021                    pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
2022                    pMB->mode = MODE_NOT_CODED;
2023                    return 0;
2024            }
2025    
         CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, &Data);  
2026          if (!(mask = make_mask(pmv, 1)))          if (!(mask = make_mask(pmv, 1)))
2027                  CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, &Data);                  (*CheckCandidate)(pmv[1].x, pmv[1].y, mask, &i, Data);
2028          if (!(mask = make_mask(pmv, 2)))          if (!(mask = make_mask(pmv, 2)))
2029                  CheckCandidate16no4vI(0, 0, mask, &i, &Data);                  (*CheckCandidate)(pmv[2].x, pmv[2].y, mask, &i, Data);
   
         DiamondSearch(currentMV.x, currentMV.y, &Data, i);  
2030    
2031          pMB->mvs[0] = pMB->mvs[1]          if (*Data->iMinSAD > MAX_SAD00_FOR_SKIP * 4) // diamond only if needed
2032                          = pMB->mvs[2] = pMB->mvs[3] = currentMV; // all, for future get_pmv()                  DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
2033    
2034          return iMinSAD;          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
2035            pMB->mode = MODE_INTER;
2036            return *(Data->iMinSAD);
2037  }  }
2038    
2039  #define INTRA_THRESH    1350  #define INTRA_THRESH    1350
2040  #define INTER_THRESH    900  #define INTER_THRESH    900
2041    
2042    
2043  int  int
2044  MEanalysis(     const IMAGE * const pRef,  MEanalysis(     const IMAGE * const pRef,
2045                          const IMAGE * const pCurrent,                          FRAMEINFO * const Current,
2046                          MBParam * const pParam,                          MBParam * const pParam,
2047                          MACROBLOCK * const pMBs,                          int maxIntra, //maximum number if non-I frames
2048                          const uint32_t iFcode)                          int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame
2049                            int bCount) // number if B frames in a row
2050  {  {
2051          uint32_t x, y, intra = 0;          uint32_t x, y, intra = 0;
2052          int sSAD = 0;          int sSAD = 0;
2053            MACROBLOCK * const pMBs = Current->mbs;
2054            const IMAGE * const pCurrent = &Current->image;
2055            int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH;
2056    
2057            VECTOR currentMV;
2058            int32_t iMinSAD;
2059            SearchData Data;
2060            Data.iEdgedWidth = pParam->edged_width;
2061            Data.currentMV = &currentMV;
2062            Data.iMinSAD = &iMinSAD;
2063            Data.iFcode = Current->fcode;
2064            CheckCandidate = CheckCandidate16no4vI;
2065    
2066            if (intraCount < 10) // we're right after an I frame
2067                    IntraThresh += 4 * (intraCount - 10) * (intraCount - 10);
2068            else
2069                    if ( 5*(maxIntra - intraCount) < maxIntra) // we're close to maximum. 2 sec when max is 10 sec
2070                            IntraThresh -= (IntraThresh * (maxIntra - 5*(maxIntra - intraCount)))/maxIntra;
2071    
2072    
2073            InterThresh += 300 * (1 - bCount);
2074            if (InterThresh < 200) InterThresh = 200;
2075    
2076          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
2077    
2078          for (y = 0; y < pParam->mb_height-1; y++) {          for (y = 1; y < pParam->mb_height-1; y++) {
2079                  for (x = 0; x < pParam->mb_width; x++) {                  for (x = 1; x < pParam->mb_width-1; x++) {
2080                          int sad, dev;                          int sad, dev;
   
2081                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2082    
2083                          sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,                          sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
2084                                                                  iFcode, pParam, pMBs, pMB);                                                                  pParam, pMBs, pMB, &Data);
2085    
2086                          if ( x != 0 && y != 0 && x != pParam->mb_width-1 ) { //no edge macroblocks, they just don't work                          if (sad > IntraThresh) {
                                 if (sad > INTRA_THRESH) {  
2087                                          dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                          dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
2088                                                                    pParam->edged_width);                                                                    pParam->edged_width);
2089                                          if (dev + INTRA_THRESH < sad) intra++;                                  if (dev + IntraThresh < sad) {
2090                                          if (intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame                                          pMB->mode = MODE_INTRA;
2091                                            if (++intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame
2092                                  }                                  }
                                 sSAD += sad;  
2093                          }                          }
2094                            sSAD += sad;
2095                  }                  }
2096          }          }
2097          sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);          sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2098          if (sSAD > INTER_THRESH ) return 1; //P frame          if (sSAD > InterThresh ) return 1; //P frame
2099          emms();          emms();
2100          return 0; // B frame          return 0; // B frame
2101    
2102  }  }
2103    
2104    int
2105    FindFcode(      const MBParam * const pParam,
2106                            const FRAMEINFO * const current)
2107    {
2108            uint32_t x, y;
2109            int max = 0, min = 0, i;
2110    
2111            for (y = 0; y < pParam->mb_height; y++) {
2112                    for (x = 0; x < pParam->mb_width; x++) {
2113    
2114                            MACROBLOCK *pMB = &current->mbs[x + y * pParam->mb_width];
2115                            for(i = 0; i < (pMB->mode == MODE_INTER4V ? 4:1); i++) {
2116                                    if (pMB->mvs[i].x > max) max = pMB->mvs[i].x;
2117                                    if (pMB->mvs[i].y > max) max = pMB->mvs[i].y;
2118    
2119                                    if (pMB->mvs[i].x < min) min = pMB->mvs[i].x;
2120                                    if (pMB->mvs[i].y < min) min = pMB->mvs[i].y;
2121                            }
2122                    }
2123            }
2124    
2125            min = -min;
2126            max += 1;
2127            if (min > max) max = min;
2128            if (pParam->m_quarterpel) max *= 2;
2129    
2130            for (i = 1; (max > 32 << (i - 1)); i++);
2131            return i;
2132    }
2133    
2134    static void
2135    CheckGMC(int x, int y, const int dir, int * iDirection,
2136                    const MACROBLOCK * const pMBs, uint32_t * bestcount, VECTOR * GMC,
2137                    const MBParam * const pParam)
2138    {
2139            uint32_t mx, my, a, count = 0;
2140    
2141            for (my = 1; my < pParam->mb_height-1; my++)
2142                    for (mx = 1; mx < pParam->mb_width-1; mx++) {
2143                            VECTOR mv;
2144                            const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2145                            if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED) continue;
2146                            mv = pMB->mvs[0];
2147                            a = ABS(mv.x - x) + ABS(mv.y - y);
2148                            if (a < 6) count += 6 - a;
2149                    }
2150    
2151            if (count > *bestcount) {
2152                    *bestcount = count;
2153                    *iDirection = dir;
2154                    GMC->x = x; GMC->y = y;
2155            }
2156    }
2157    
2158    
2159    static VECTOR
2160    GlobalMotionEst(const MACROBLOCK * const pMBs, const MBParam * const pParam, const uint32_t iFcode)
2161    {
2162    
2163            uint32_t count, bestcount = 0;
2164            int x, y;
2165            VECTOR gmc = {0,0};
2166            int step, min_x, max_x, min_y, max_y;
2167            uint32_t mx, my;
2168            int iDirection, bDirection;
2169    
2170            min_x = min_y = -32<<iFcode;
2171            max_x = max_y = 32<<iFcode;
2172    
2173    //step1: let's find a rough camera panning
2174            for (step = 32; step >= 2; step /= 2) {
2175                    bestcount = 0;
2176                    for (y = min_y; y <= max_y; y += step)
2177                            for (x = min_x ; x <= max_x; x += step) {
2178                                    count = 0;
2179                                    //for all macroblocks
2180                                    for (my = 1; my < pParam->mb_height-1; my++)
2181                                            for (mx = 1; mx < pParam->mb_width-1; mx++) {
2182                                                    const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2183                                                    VECTOR mv;
2184    
2185                                                    if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
2186                                                            continue;
2187    
2188                                                    mv = pMB->mvs[0];
2189                                                    if ( ABS(mv.x - x) <= step && ABS(mv.y - y) <= step )   /* GMC translation is always halfpel-res */
2190                                                            count++;
2191                                            }
2192                                    if (count >= bestcount) { bestcount = count; gmc.x = x; gmc.y = y; }
2193                            }
2194                    min_x = gmc.x - step;
2195                    max_x = gmc.x + step;
2196                    min_y = gmc.y - step;
2197                    max_y = gmc.y + step;
2198    
2199            }
2200    
2201            if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10)
2202                    gmc.x = gmc.y = 0; //no camara pan, no GMC
2203    
2204    // step2: let's refine camera panning using gradiend-descent approach.
2205    // TODO: more warping points may be evaluated here (like in interpolate mode search - two vectors in one diamond)
2206            bestcount = 0;
2207            CheckGMC(gmc.x, gmc.y, 255, &iDirection, pMBs, &bestcount, &gmc, pParam);
2208            do {
2209                    x = gmc.x; y = gmc.y;
2210                    bDirection = iDirection; iDirection = 0;
2211                    if (bDirection & 1) CheckGMC(x - 1, y, 1+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2212                    if (bDirection & 2) CheckGMC(x + 1, y, 2+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2213                    if (bDirection & 4) CheckGMC(x, y - 1, 1+2+4, &iDirection, pMBs, &bestcount, &gmc, pParam);
2214                    if (bDirection & 8) CheckGMC(x, y + 1, 1+2+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2215    
2216            } while (iDirection);
2217    
2218            if (pParam->m_quarterpel) {
2219                    gmc.x *= 2;
2220                    gmc.y *= 2;     /* we store the halfpel value as pseudo-qpel to make comparison easier */
2221            }
2222    
2223            return gmc;
2224    }

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

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