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

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

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

revision 530, Mon Sep 23 20:36:02 2002 UTC revision 663, Wed Nov 20 15:29:07 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"
44    #include "../utils/emms.h"
45    
46  #define INITIAL_SKIP_THRESH     (10)  #define INITIAL_SKIP_THRESH     (10)
47  #define FINAL_SKIP_THRESH       (50)  #define FINAL_SKIP_THRESH       (50)
48  #define MAX_SAD00_FOR_SKIP      (20)  #define MAX_SAD00_FOR_SKIP      (20)
49  #define MAX_CHROMA_SAD_FOR_SKIP (18)  #define MAX_CHROMA_SAD_FOR_SKIP (22)
50  #define SKIP_THRESH_B (10)  #define SKIP_THRESH_B (25)
51    
52  #define CHECK_CANDIDATE(X,Y,D) { \  #define CHECK_CANDIDATE(X,Y,D) { \
53  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }
54    
55  #define iDiamondSize 2  #define iDiamondSize 2
56    
 //FILE * debug;  
   
57  static __inline int  static __inline int
58  d_mv_bits(int x, int y, const uint32_t iFcode)  d_mv_bits(int x, int y, const uint32_t iFcode)
59  {  {
# Line 79  Line 79 
79          return xb + yb;          return xb + yb;
80  }  }
81    
82  /* CHACK_CANDIATE FUNCTIONS START */  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;
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);
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);
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;
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);
199                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding);
200                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding);
201                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding);
202                    break;
203    
204            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);
207                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding);
208                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding);
209                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding);
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 */
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;
 //      static int32_t sad[5];  
         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 126  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 = sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);
307            sad += (data->lambda16 * t * sad)/1000;
308    
309            if (sad < *(data->iMinSAD)) {
310                    *(data->iMinSAD) = sad;
311                    current->x = x; current->y = y;
312                    *dir = Direction; }
313    }
314    
315    static void
316    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;
320    
321            if (( x > data->max_dx) || ( x < data->min_dx)
322                    || ( 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),
325                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);                                          data->iEdgedWidth, 256*4096);
         sad += sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);  
326    
327          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
328                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 148  Line 330 
330                  *dir = Direction; }                  *dir = Direction; }
331  }  }
332    
333    
334  static void  static void
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 196  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 214  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 249  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 268  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;  
         }  
   
         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;  
450          }          }
451            ReferenceF = Interpolate16x16qpel(mvs.x, mvs.y, 0, data);
452            ReferenceB = Interpolate16x16qpel(b_mvs.x, b_mvs.y, 1, data);
453    
454          sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
455            sad += (data->lambda16 * d_mv_bits(x, y, 1) * sad)/1000;
456    
457          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
458                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 293  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 316  Line 484 
484                  *dir = Direction; }                  *dir = Direction; }
485  }  }
486    
487  /* CHACK_CANDIATE FUNCTIONS END */  /* CHECK_CANDIATE FUNCTIONS END */
488    
489  /* MAINSEARCH FUNCTIONS START */  /* MAINSEARCH FUNCTIONS START */
490    
# Line 465  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 497  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 508  Line 679 
679  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)
680  {  {
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 = pMB->mv16.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 = pMB->mv16.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 530  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
712            int32_t temp[5];
713            VECTOR currentMV[5];
714            VECTOR currentQMV[5];
715            int32_t iMinSAD[5];
716            SearchData Data;
717            Data.iEdgedWidth = pParam->edged_width;
718            Data.currentMV = currentMV;
719            Data.currentQMV = currentQMV;
720            Data.iMinSAD = iMinSAD;
721            Data.temp = temp;
722            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                                                  current->fcode, 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 582  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->mv16 = 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 601  Line 832 
832  static __inline int  static __inline int
833  make_mask(const VECTOR * const pmv, const int i)  make_mask(const VECTOR * const pmv, const int i)
834  {  {
835          int mask = 0xFF, j;          int mask = 255, j;
836          for (j = 0; j < i; j++) {          for (j = 0; j < i; j++) {
837                  if (MVequal(pmv[i], pmv[j])) return 0; // same vector has been checked already                  if (MVequal(pmv[i], pmv[j])) return 0; // same vector has been checked already
838                  if (pmv[i].x == pmv[j].x) {                  if (pmv[i].x == pmv[j].x) {
# Line 625  Line 856 
856    
857          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour
858                  pmv[5].x = EVEN(pmv[3].x);                  pmv[5].x = EVEN(pmv[3].x);
859                  pmv[5].y = EVEN(pmv[3].y); }                  pmv[5].y = EVEN(pmv[3].y);
860          else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
861    
862          if (x != 0) { pmv[3].x = EVEN(pmv[1].x); pmv[3].y = EVEN(pmv[1].y); }// pmv[3] is left neighbour          if (x != 0) { pmv[3].x = EVEN(pmv[1].x); pmv[3].y = EVEN(pmv[1].y); }// pmv[3] is left neighbour
863          else pmv[3].x = pmv[3].y = 0;          else pmv[3].x = pmv[3].y = 0;
# Line 644  Line 875 
875    
876          if ((x != iWcount-1) && (y != iHcount-1)) {          if ((x != iWcount-1) && (y != iHcount-1)) {
877                  pmv[6].x = EVEN((prevMB+1+iWcount)->mvs[0].x); //[6] right-down neighbour in last frame                  pmv[6].x = EVEN((prevMB+1+iWcount)->mvs[0].x); //[6] right-down neighbour in last frame
878                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y); }                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
879          else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
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 658  Line 889 
889                  const int y,                  const int y,
890                  const uint32_t MotionFlags,                  const uint32_t MotionFlags,
891                  const uint32_t iQuant,                  const uint32_t iQuant,
892                  const uint32_t iFcode,                  SearchData * const Data,
893                  const MBParam * const pParam,                  const MBParam * const pParam,
894                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
895                  const MACROBLOCK * const prevMBs,                  const MACROBLOCK * const prevMBs,
# Line 666  Line 897 
897                  MACROBLOCK * const pMB)                  MACROBLOCK * const pMB)
898  {  {
899    
         const int32_t iEdgedWidth = pParam->edged_width;  
   
900          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
901          int32_t temp[5];          VECTOR pmv[7];
         VECTOR currentMV[5], pmv[7];  
         int32_t psad[4], iMinSAD[5];  
         MainSearchFunc * MainSearchPtr;  
         SearchData Data;  
902    
903          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, psad);  //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, iFcode);                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
906    
907          Data.predMV = pmv[0];          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
908          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8;
909          Data.iEdgedWidth = iEdgedWidth;          Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8;
910          Data.currentMV = currentMV;  
911          Data.iMinSAD = iMinSAD;          Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16;
912          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
913          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
914          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
915          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;          Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
916          Data.temp = temp;          Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
917    
918          Data.iQuant = iQuant;          Data->lambda16 = lambda_vec16[iQuant];
919          Data.iFcode = iFcode;          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);
924                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
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); }
   
         for(i = 0;  i < 5; i++) currentMV[i].x = currentMV[i].y = 0;  
   
         i = d_mv_bits(pmv[0].x, pmv[0].y, iFcode);  
   
         iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;  
         iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;  
         iMinSAD[2] = pMB->sad8[1];  
         iMinSAD[3] = pMB->sad8[2];  
         iMinSAD[4] = pMB->sad8[3];  
927    
928          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
929    
930            for(i = 0;  i < 5; i++)
931                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
932    
933            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);
937            Data->iMinSAD[0] = pMB->sad16 + (Data->lambda16 * i * pMB->sad16)/1000;
938            Data->iMinSAD[1] = pMB->sad8[0] + (Data->lambda8 * i * (pMB->sad8[0]+NEIGH_8X8_BIAS))/100;
939            Data->iMinSAD[2] = pMB->sad8[1];
940            Data->iMinSAD[3] = pMB->sad8[2];
941            Data->iMinSAD[4] = pMB->sad8[3];
942    
943          if ((x == 0) && (y == 0)) threshA = 512;          if ((x == 0) && (y == 0)) threshA = 512;
944          else {          else {
945                  threshA = psad[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) CheckCandidate = CheckCandidate16;          if (inter4v || Data->chroma) CheckCandidate = CheckCandidate16;
953          else CheckCandidate = CheckCandidate16no4v;          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 (iMinSAD[0] < threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
961          }          }
962    
963          if ((iMinSAD[0] <= threshA) ||          if ((Data->iMinSAD[0] <= threshA) ||
964                          (MVequal(currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
965                          (iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {                          (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {
966                  inter4v = 0;                  inter4v = 0;
967                  if (MotionFlags & PMV_QUICKSTOP16) goto PMVfast16_Terminate_without_Refine;          } else {
                 if (MotionFlags & PMV_EARLYSTOP16) {  
                         CheckCandidate = CheckCandidate16no4v; // I sure hope it's faster  
                         goto PMVfast16_Terminate_with_Refine;  
                 }  
         }  
968    
969          if (MotionFlags & PMV_USESQUARES16)                  MainSearchFunc * MainSearchPtr;
970                  MainSearchPtr = SquareSearch;                  if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
971          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
                 MainSearchPtr = AdvDiamondSearch;  
972                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
973    
974          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, iDirection);                  (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
975    
976  /* extended search, diamond starting in 0,0 and in prediction.  /* extended search, diamond starting in 0,0 and in prediction.
977          note that this search is/might be done in halfpel positions,          note that this search is/might be done in halfpel positions,
# Line 756  Line 979 
979    
980          if (MotionFlags & PMV_EXTSEARCH16) {          if (MotionFlags & PMV_EXTSEARCH16) {
981                  int32_t bSAD;                  int32_t bSAD;
982                  VECTOR startMV = Data.predMV, backupMV = currentMV[0];                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
983                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?
984                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);
985                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
986                          bSAD = iMinSAD[0]; 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 < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
991                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
992                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
993                  }                  }
994    
995                  backupMV = currentMV[0];                          backupMV = Data->currentMV[0];
996                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;
997                  else startMV.x = startMV.y = 0;                  else startMV.x = startMV.y = 0;
998                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
999                          bSAD = iMinSAD[0]; 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 < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1004                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1005                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1006                            }
1007                    }
1008                  }                  }
1009    
1010            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  PMVfast16_Terminate_with_Refine:          if (Data->iMinSAD[0] < (int32_t)iQuant * 30 ) inter4v = 0;
1027            if (inter4v) {
1028                    SearchData Data8;
1029                    Data8.iFcode = Data->iFcode;
1030                    Data8.lambda8 = Data->lambda8;
1031                    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);
1035                    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);
1037                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1038    
1039          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);                  if (Data->chroma) {
1040                            int sumx, sumy, dx, dy;
1041    
1042  PMVfast16_Terminate_without_Refine:                          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          if (inter4v)                          Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);
1053                  for(i = 0; i < 4; i++)                  }
1054                          Search8(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);          }
1055    
1056          if (!(inter4v) ||          if (!(inter4v) ||
1057                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
1058                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1059  // INTER MODE  // INTER MODE
1060                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1061                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1062                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1063    
1064                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1065                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1066    
1067                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1068                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          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;
1074                            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 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1080                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1081          }          }
   
1082  }  }
1083    
1084  static void  static void
# Line 820  Line 1088 
1088                  const MBParam * const pParam,                  const MBParam * const pParam,
1089                  MACROBLOCK * const pMB,                  MACROBLOCK * const pMB,
1090                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
1091                  const int block)                  const int block,
1092                    SearchData * const Data)
1093  {  {
1094          SearchData Data;          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1095            Data->currentMV = OldData->currentMV + 1 + block;
1096          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          Data->currentQMV = OldData->currentQMV + 1 + block;
1097          Data.iMinSAD = OldData->iMinSAD + 1 + block;  
1098          Data.currentMV = OldData->currentMV+1+block;          if(pParam->m_quarterpel) {
1099          Data.iFcode = OldData->iFcode;                  Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1100          Data.iQuant = OldData->iQuant;                  if (block != 0) *(Data->iMinSAD) += (Data->lambda8 *
1101                                                                            d_mv_bits(      Data->currentQMV->x - Data->predMV.x,
1102          if (block != 0)                                                                                                  Data->currentQMV->y - Data->predMV.y,
1103                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *                                                                                                  Data->iFcode) * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
1104                                                                  d_mv_bits(      Data.currentMV->x - Data.predMV.x,          } else {
1105                                                                                          Data.currentMV->y - Data.predMV.y,                  Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1106                                                                                          Data.iFcode);                  if (block != 0) *(Data->iMinSAD) += (Data->lambda8 *
1107                                                                            d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1108                                                                                                    Data->currentMV->y - Data->predMV.y,
1109                                                                                                    Data->iFcode) * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
1110            }
1111    
1112          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
1113    
1114                  Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));
1115                  Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));
1116                  Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));
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));
   
                 Data.iEdgedWidth = pParam->edged_width;  
   
                 Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));  
1118    
1119                  get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
1120                                  pParam->width, pParam->height, OldData->iFcode);                  Data->qpel_precision = 0;
1121    
1122                    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->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(*(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 (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);          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;
1171                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1172          }          }
1173    
1174          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;          pMB->mvs[block] = *(Data->currentMV);
1175          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;          pMB->sad8[block] =  4 * (*Data->iMinSAD);
         pMB->mvs[block] = *(Data.currentMV);  
         pMB->sad8[block] =  4 * (*(Data.iMinSAD));  
1176  }  }
1177    
1178  /* B-frames code starts here */  /* B-frames code starts here */
# Line 896  Line 1200 
1200          pmv[2] = ChoosePred(pMB, mode_curr);          pmv[2] = ChoosePred(pMB, mode_curr);
1201          pmv[2].x = EVEN(pmv[2].x); pmv[2].y = EVEN(pmv[2].y);          pmv[2].x = EVEN(pmv[2].x); pmv[2].y = EVEN(pmv[2].y);
1202    
         pmv[3].x = pmv[3].y = 0;  
1203          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour
1204                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);
1205                  pmv[3].x = EVEN(pmv[3].x); pmv[3].y = EVEN(pmv[3].y); }                  pmv[3].x = EVEN(pmv[3].x); pmv[3].y = EVEN(pmv[3].y);
1206            } else pmv[3].x = pmv[3].y = 0;
1207    
1208          if (y != 0) {          if (y != 0) {
1209                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);
# Line 929  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    
1254          Data.iMinSAD = &iMinSAD;          Data->Ref = pRef + (x + y * iEdgedWidth) * 16;
1255          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->RefH = pRefH + (x + y * iEdgedWidth) * 16;
1256          Data.iEdgedWidth = iEdgedWidth;          Data->RefV = pRefV + (x + y * iEdgedWidth) * 16;
1257          Data.currentMV = &currentMV;          Data->RefHV = pRefHV + (x + y * iEdgedWidth) * 16;
         Data.iMinSAD = &iMinSAD;  
         Data.Ref = pRef + (x + y * iEdgedWidth) * 16;  
         Data.RefH = pRefH + (x + y * iEdgedWidth) * 16;  
         Data.RefV = pRefV + (x + y * iEdgedWidth) * 16;  
         Data.RefHV = pRefHV + (x + y * iEdgedWidth) * 16;  
   
         Data.iQuant = iQuant;  
         Data.iFcode = iFcode;  
         Data.predMV = *predMV;  
   
         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 990  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 (*Data->iMinSAD < *best_sad) {
1302          if (iMinSAD < *best_sad) {                  *best_sad = *Data->iMinSAD;
                 *best_sad = 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  }  }
1323    
1324  static int32_t  static int32_t
1325  SearchDirect(const uint8_t * const f_Ref,  SearchDirect(const IMAGE * const f_Ref,
1326                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1327                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
1328                                  const uint8_t * const f_RefHV,                                  const uint8_t * const f_RefHV,
1329                                  const uint8_t * const b_Ref,                                  const IMAGE * const b_Ref,
1330                                  const uint8_t * const b_RefH,                                  const uint8_t * const b_RefH,
1331                                  const uint8_t * const b_RefV,                                  const uint8_t * const b_RefV,
1332                                  const uint8_t * const b_RefHV,                                  const uint8_t * const b_RefHV,
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 = 0, 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 + (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 + (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;
   
         if (( pMB->mvs[k].x > Data.max_dx ) || ( pMB->mvs[k].x < Data.min_dx )  
                         || ( pMB->mvs[k].y > Data.max_dy ) || ( pMB->mvs[k].y < Data.min_dy )  
                         || ( pMB->b_mvs[k].x > Data.max_dx ) || ( pMB->b_mvs[k].x < Data.min_dx )  
                         || ( pMB->b_mvs[k].y > Data.max_dy ) || ( pMB->b_mvs[k].y < Data.min_dy )) {  
 /*  
                 fprintf(debug, "\nERROR - out of range : vector %d,%d and %d,%d\n", pMB->mvs[k].x, pMB->mvs[k].y,pMB->b_mvs[k].x,pMB->b_mvs[k].y );  
                 fprintf(debug, " range is x: %d..%d y: %d..%d \n", Data.min_dx,Data.max_dx,Data.min_dy,Data.max_dy);  
                 fprintf(debug,"macroblock %d, %d \n", x, y);  
                 fprintf(debug, "direct MV is %d,%d \n", directmv[k].x, directmv[k].y);  
 */  
                 *best_sad = 256*4096; // in that case, we won't use direct mode  
                 pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"  
                 pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;  /* because backwards and interpol might rely on this */  
                 return 0; }  
1378    
1379                    if ( ( pMB->b_mvs[k].x > Data->max_dx ) || ( pMB->b_mvs[k].x < Data->min_dx )
1380                            || ( 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
1383                            pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
1384                            pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;
1385                            return 0;
1386                    }
1387          if (b_mb->mode != MODE_INTER4V) {          if (b_mb->mode != MODE_INTER4V) {
1388                  iMinSAD = sad16bi(Data.Cur,                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1389                                                  get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,                          pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];
1390                                                                  x, y, 16, &pMB->mvs[0], iEdgedWidth),                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1391                                                  get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1392                                                                  x, y, 16, &pMB->b_mvs[0], iEdgedWidth), iEdgedWidth);                          break;
1393                    }
                 Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];  
                 Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];  
                 break;  
         }  
         iMinSAD += sad8bi(Data.Cur + (k&1)*8 + (k>>1)* 8 * iEdgedWidth,  
                                                 get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,  
                                                                 (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->mvs[k], iEdgedWidth),  
                                                 get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,  
                                                                 (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->b_mvs[k], iEdgedWidth),  
                                                 iEdgedWidth);  
1394          }          }
1395    
1396    
1397            if (b_mb->mode == MODE_INTER4V) CheckCandidate = CheckCandidateDirect;
1398            else CheckCandidate = CheckCandidateDirectno4v;
1399    
1400            (*CheckCandidate)(0, 0, 255, &k, Data);
1401    
1402  // skip decision  // skip decision
1403          if (iMinSAD < (int32_t)iQuant * SKIP_THRESH_B) {          if (*Data->iMinSAD < pMB->quant * SKIP_THRESH_B) {
1404                    //possible skip - checking chroma. everything copied from MC
1405                    //this is not full chroma compensation, only it's fullpel approximation. should work though
1406                    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;
1421                            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;
1423                            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;
1426                            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;
1428                            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                    if (sum < MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) {
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;
         iMinSAD += 2 * lambda_vec16[iQuant]; // 2 bits needed to code vector 0,0  
         currentMV.x = currentMV.y = 0;  
         if (b_mb->mode == MODE_INTER4V)  
                 CheckCandidate = CheckCandidateDirect;  
         else CheckCandidate = CheckCandidateDirectno4v;  
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 1123  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 1168  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;  
1521    
1522            *(bData.iMinSAD = fData->iMinSAD) = 4096*256;
1523            bData.Cur = fData->Cur;
1524            fData->iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;
1525            bData.currentMV = fData->currentMV + 1; bData.currentQMV = fData->currentQMV + 1;
1526            bData.lambda16 = fData->lambda16;
1527            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1528    
1529            bData.bRef = fData->Ref = f_Ref + (x + y * iEdgedWidth) * 16;
1530            bData.bRefH = fData->RefH = f_RefH + (x + y * iEdgedWidth) * 16;
1531            bData.bRefV = fData->RefV = f_RefV + (x + y * iEdgedWidth) * 16;
1532            bData.bRefHV = fData->RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;
1533            bData.Ref = fData->bRef = b_Ref + (x + y * iEdgedWidth) * 16;
1534            bData.RefH = fData->bRefH = b_RefH + (x + y * iEdgedWidth) * 16;
1535            bData.RefV = fData->bRefV = b_RefV + (x + y * iEdgedWidth) * 16;
1536            bData.RefHV = fData->bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;
1537            bData.RefQ = fData->RefQ;
1538            fData->qpel_precision = bData.qpel_precision = 0;
1539            bData.rounding = 0;
1540    
1541            bData.bpredMV = fData->predMV = *f_predMV;
1542            fData->bpredMV = bData.predMV = *b_predMV;
1543    
1544            fData->currentMV[0] = fData->currentMV[2];
1545            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            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    
1548            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 (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dx;
1551            if (fData->currentMV[0].y > fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1552    
1553            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          fData.iMinSAD = bData.iMinSAD = &iMinSAD;          CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
   
         fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
         fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;  
         fData.currentMV = currentMV; bData.currentMV = currentMV + 1;  
         fData.iQuant = bData.iQuant = iQuant;  
         fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;  
   
   
         bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  
         bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;  
         bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;  
         bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;  
         bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;  
         bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;  
         bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;  
         bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;  
   
         bData.bpredMV = fData.predMV = *f_predMV;  
         fData.bpredMV = bData.predMV = *b_predMV;  
   
   
         currentMV[0] = pMB->mvs[0];  
         currentMV[1] = pMB->b_mvs[0];  
         get_range(&fData.min_dx, &fData.max_dx, &fData.min_dy, &fData.max_dy, x, y, 16, pParam->width, pParam->height, fcode);  
         get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode);  
   
         CheckCandidateInt(currentMV[0].x, 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 + 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1568                  CheckCandidateInt(i, j + 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1569                  CheckCandidateInt(i - 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1570                  CheckCandidateInt(i, j - 2, 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);
1576                  CheckCandidateInt(i + 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1577                  CheckCandidateInt(i, j + 2, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
1578                  CheckCandidateInt(i - 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, &bData);
                 CheckCandidateInt(i, j - 2, 0, &iDirection, &bData);  
1579    
1580          } while (!(iDirection));          } while (!(iDirection));
1581    
1582  /* halfpel refinement. luckly we can use normal halfpel function for it */          *fData->iMinSAD +=  2 * fData->lambda16; // two bits are needed to code interpolate mode.
   
         if (MotionFlags & PMV_HALFPELREFINE16) {  
                 CheckCandidate = CheckCandidateInt;  
                 HalfpelRefine(&fData);  
                 currentMV[2] = currentMV[0];  
                 HalfpelRefine(&bData);  
         }  
1583    
1584  // two bits are needed to code interpolate mode. we treat the bits just like they were vector's          if (fData->qpel) {
1585          iMinSAD +=  2 * lambda_vec16[iQuant];                  fData->qpel_precision = bData.qpel_precision = 1;
1586          if (iMinSAD < *best_sad) {                  get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, 0);
1587                  *best_sad = iMinSAD;                  get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, 0);
1588                  pMB->mvs[0] = currentMV[0];                  fData->currentQMV[2].x = fData->currentQMV[0].x = 2 * fData->currentMV[0].x;
1589                  pMB->b_mvs[0] = currentMV[1];                  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;                  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 1277  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 1287  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 1303  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,
1689                          skip_sad = SearchDirect(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,
                                                                         b_ref->y, 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    
                         if (!(frame->global_flags & XVID_HALFPEL)) best_sad = skip_sad = 256*4096;  
                         else  
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 1354  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 1381  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 1455  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 1526  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->mv16 = 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 1568  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    
1951          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
1952                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
                         int32_t sad00;  
1953    
1954                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
1955    
# Line 1583  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                          if (pMB->dquant == NO_CHANGE) //no skip otherwise, anyway                          SearchPhinted(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
1972                                  sad00 = pMB->sad16                                                          y, current->motion_flags, pMB->quant,
1973                                          = sad16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
1974                                                                  pRef->y + (x + y * pParam->edged_width) * 16,                                                          &Data);
                                                                 pParam->edged_width, 256*4096 );  
                         else sad00 = 256*4096;  
1975    
1976                    }
1977            }
1978            free(qimage);
1979    }
1980    
1981  //initial skip decision  static __inline int
1982    MEanalyzeMB (   const uint8_t * const pRef,
1983                                    const uint8_t * const pCur,
1984                                    const int x,
1985                                    const int y,
1986                                    const MBParam * const pParam,
1987                                    const MACROBLOCK * const pMBs,
1988                                    MACROBLOCK * const pMB,
1989                                    SearchData * const Data)
1990    {
1991    
1992                          if ( (pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)          int i = 255, mask;
1993                                  && ( //(pMB->mode == MODE_NOT_CODED) ||          VECTOR pmv[3];
1994                                          (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant) )) ) {          *(Data->iMinSAD) = MV_MAX_ERROR;
1995                                  if (sad00 < pMB->quant * INITIAL_SKIP_THRESH) {  
1996                                          SkipMacroblockP(pMB, sad00);          //median is only used as prediction. it doesn't have to be real
1997                                          continue; } //skipped          if (x == 1 && y == 1) Data->predMV.x = Data->predMV.y = 0;
1998            else
1999                    if (x == 1) //left macroblock does not have any vector now
2000                            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            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2006                                    pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
2007    
2008            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);
2012            pmv[1].y = EVEN(pMB->mvs[0].y);
2013            pmv[2].x = EVEN(Data->predMV.x);
2014            pmv[2].y = EVEN(Data->predMV.y);
2015            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                          }                          }
                         else sad00 = 256*4096;  
2025    
2026                          if (pMB->mode == MODE_NOT_CODED)          if (!(mask = make_mask(pmv, 1)))
2027                                  SearchP(        pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                  (*CheckCandidate)(pmv[1].x, pmv[1].y, mask, &i, Data);
2028                                                          y, current->motion_flags, pMB->quant,          if (!(mask = make_mask(pmv, 2)))
2029                                                          current->fcode, pParam, pMBs, reference->mbs,                  (*CheckCandidate)(pmv[2].x, pmv[2].y, mask, &i, Data);
2030                                                          current->global_flags & XVID_INTER4V, pMB);  
2031            if (*Data->iMinSAD > MAX_SAD00_FOR_SKIP * 4) // diamond only if needed
2032                    DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
2033    
2034            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
2040    #define INTER_THRESH    900
2041    
2042    
2043    int
2044    MEanalysis(     const IMAGE * const pRef,
2045                            FRAMEINFO * const Current,
2046                            MBParam * const pParam,
2047                            int maxIntra, //maximum number if non-I frames
2048                            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;
2052            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                          else
2069                                  SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                  if ( 5*(maxIntra - intraCount) < maxIntra) // we're close to maximum. 2 sec when max is 10 sec
2070                                                          y, current->motion_flags, pMB->quant,                          IntraThresh -= (IntraThresh * (maxIntra - 5*(maxIntra - intraCount)))/maxIntra;
                                                         current->fcode, pParam, pMBs,  
                                                         current->global_flags & XVID_INTER4V, pMB);  
2071    
 /* final skip decision, a.k.a. "the vector you found, really that good?" */  
                         if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)  
                                 if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)  
                                 SkipMacroblockP(pMB, sad00);  
2072    
2073            InterThresh += 300 * (1 - bCount);
2074            if (InterThresh < 200) InterThresh = 200;
2075    
2076            if (sadInit) (*sadInit) ();
2077    
2078            for (y = 1; y < pParam->mb_height-1; y++) {
2079                    for (x = 1; x < pParam->mb_width-1; x++) {
2080                            int sad, dev;
2081                            MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2082    
2083                            sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
2084                                                                    pParam, pMBs, pMB, &Data);
2085    
2086                            if (sad > IntraThresh) {
2087                                    dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
2088                                                              pParam->edged_width);
2089                                    if (dev + IntraThresh < sad) {
2090                                            pMB->mode = MODE_INTRA;
2091                                            if (++intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame
2092                                    }
2093                            }
2094                            sSAD += sad;
2095                    }
2096            }
2097            sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2098            if (sSAD > InterThresh ) return 1; //P frame
2099            emms();
2100            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.530  
changed lines
  Added in v.663

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