[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 675, Sun Nov 24 16:38:11 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 (15)
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 + 16*dir;
141            const int32_t iEdgedWidth = data->iEdgedWidth;
142            const uint32_t rounding = data->rounding;
143            const int halfpel_x = x/2;
144            const int halfpel_y = y/2;
145            const uint8_t *ref1, *ref2, *ref3, *ref4;
146    
147            ref1 = GetReference(halfpel_x, halfpel_y, dir, data); // this reference is used in all cases
148            ref1 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
149            switch( ((x&1)<<1) + (y&1) ) {
150            case 0: // pure halfpel position
151                    Reference = (uint8_t *) GetReference(halfpel_x, halfpel_y, dir, data);
152                    Reference += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
153                    break;
154    
155            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
156                    ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);
157                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
158                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
159                    break;
160    
161            case 2: // x qpel, y halfpel - left or right during qpel refinement
162                    ref2 = GetReference(x - halfpel_x, halfpel_y, dir, data);
163                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
164                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
165                    break;
166    
167            default: // x and y in qpel resolution - the "corners" (top left/right and
168                             // bottom left/right) during qpel refinement
169                    ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);
170                    ref3 = GetReference(x - halfpel_x, halfpel_y, dir, data);
171                    ref4 = GetReference(x - halfpel_x, y - halfpel_y, dir, data);
172                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
173                    ref3 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
174                    ref4 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
175                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
176                    break;
177            }
178            return Reference;
179    }
180    
181    static uint8_t *
182    Interpolate16x16qpel(const int x, const int y, const int dir, const SearchData * const data)
183    {
184    // create or find a qpel-precision reference picture; return pointer to it
185            uint8_t * Reference = (uint8_t *)data->RefQ + 16*dir;
186            const int32_t iEdgedWidth = data->iEdgedWidth;
187            const uint32_t rounding = data->rounding;
188            const int halfpel_x = x/2;
189            const int halfpel_y = y/2;
190            const uint8_t *ref1, *ref2, *ref3, *ref4;
191    
192            ref1 = GetReference(halfpel_x, halfpel_y, dir, data); // this reference is used in all cases
193            switch( ((x&1)<<1) + (y&1) ) {
194            case 0: // pure halfpel position
195                    return (uint8_t *) GetReference(halfpel_x, halfpel_y, dir, data);
196            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
197                    ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);
198                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
199                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
200                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
201                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
202                    break;
203    
204            case 2: // x qpel, y halfpel - left or right during qpel refinement
205                    ref2 = GetReference(x - halfpel_x, halfpel_y, dir, data);
206                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
207                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
208                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
209                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
210                    break;
211    
212            default: // x and y in qpel resolution - the "corners" (top left/right and
213                             // bottom left/right) during qpel refinement
214                    ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);
215                    ref3 = GetReference(x - halfpel_x, halfpel_y, dir, data);
216                    ref4 = GetReference(x - halfpel_x, y - halfpel_y, dir, data);
217                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
218                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
219                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
220                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
221                    break;
222            }
223            return Reference;
224    }
225    
226    /* CHECK_CANDIATE FUNCTIONS START */
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's 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; bData.qpel = fData->qpel;
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_dx;
1550            if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dy;
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_dx;
1555            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dy;
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.
1583    
1584          if (MotionFlags & PMV_HALFPELREFINE16) {          if (fData->qpel) {
1585                  CheckCandidate = CheckCandidateInt;                  CheckCandidate = CheckCandidateInt;
1586                  HalfpelRefine(&fData);                  fData->qpel_precision = bData.qpel_precision = 1;
1587                  currentMV[2] = currentMV[0];                  get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, 0);
1588                  HalfpelRefine(&bData);                  get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, 0);
1589          }                  fData->currentQMV[2].x = fData->currentQMV[0].x = 2 * fData->currentMV[0].x;
1590                    fData->currentQMV[2].y = fData->currentQMV[0].y = 2 * fData->currentMV[0].y;
1591  // two bits are needed to code interpolate mode. we treat the bits just like they were vector's                  fData->currentQMV[1].x = 2 * fData->currentMV[1].x;
1592          iMinSAD +=  2 * lambda_vec16[iQuant];                  fData->currentQMV[1].y = 2 * fData->currentMV[1].y;
1593          if (iMinSAD < *best_sad) {                  SubpelRefine(fData);
1594                  *best_sad = iMinSAD;                  fData->currentQMV[2] = fData->currentQMV[0];
1595                  pMB->mvs[0] = currentMV[0];                  SubpelRefine(&bData);
1596                  pMB->b_mvs[0] = currentMV[1];          }
1597    
1598            if (*fData->iMinSAD < *best_sad) {
1599                    *best_sad = *fData->iMinSAD;
1600                    pMB->mvs[0] = fData->currentMV[0];
1601                    pMB->b_mvs[0] = fData->currentMV[1];
1602                  pMB->mode = MODE_INTERPOLATE;                  pMB->mode = MODE_INTERPOLATE;
1603                    if (fData->qpel) {
1604                            pMB->qmvs[0] = fData->currentQMV[0];
1605                            pMB->b_qmvs[0] = fData->currentQMV[1];
1606                            pMB->pmvs[1].x = pMB->qmvs[0].x - f_predMV->x;
1607                            pMB->pmvs[1].y = pMB->qmvs[0].y - f_predMV->y;
1608                            pMB->pmvs[0].x = pMB->b_qmvs[0].x - b_predMV->x;
1609                            pMB->pmvs[0].y = pMB->b_qmvs[0].y - b_predMV->y;
1610                    } else {
1611                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;
1612                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;
1613                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;
1614                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;
1615          }          }
1616  }  }
1617    }
1618    
1619  void  void
1620  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
# Line 1277  Line 1628 
1628                                           const IMAGE * const f_refV,                                           const IMAGE * const f_refV,
1629                                           const IMAGE * const f_refHV,                                           const IMAGE * const f_refHV,
1630                                           // backward (future) reference                                           // backward (future) reference
1631                                           const MACROBLOCK * const b_mbs,                                           const FRAMEINFO * const b_reference,
1632                                           const IMAGE * const b_ref,                                           const IMAGE * const b_ref,
1633                                           const IMAGE * const b_refH,                                           const IMAGE * const b_refH,
1634                                           const IMAGE * const b_refV,                                           const IMAGE * const b_refV,
# Line 1287  Line 1638 
1638          int32_t best_sad, skip_sad;          int32_t best_sad, skip_sad;
1639          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;
1640          static const VECTOR zeroMV={0,0};          static const VECTOR zeroMV={0,0};
1641            const MACROBLOCK * const b_mbs = b_reference->mbs;
1642    
1643          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
1644    
1645          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1646          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
1647            uint8_t * qimage;
1648    
1649          // note: i==horizontal, j==vertical  // some pre-inintialized data for the rest of the search
1650    
1651            SearchData Data;
1652            int32_t iMinSAD;
1653            VECTOR currentMV[3];
1654            VECTOR currentQMV[3];
1655            Data.iEdgedWidth = pParam->edged_width;
1656            Data.currentMV = currentMV; Data.currentQMV = currentQMV;
1657            Data.iMinSAD = &iMinSAD;
1658            Data.lambda16 = lambda_vec16[frame->quant];
1659            Data.qpel = pParam->m_quarterpel;
1660            Data.rounding = 0;
1661    
1662            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
1663                    return; // allocate some mem for qpel interpolated blocks
1664                                      // somehow this is dirty since I think we shouldn't use malloc outside
1665                                      // encoder_create() - so please fix me!
1666            Data.RefQ = qimage;
1667    
1668            // note: i==horizontal, j==vertical
1669          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
1670    
1671                  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 1674 
1674                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;
1675                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;
1676    
1677  /* 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 */
1678                            if (b_reference->coding_type != S_VOP)
1679                          if (b_mb->mode == MODE_NOT_CODED) {                          if (b_mb->mode == MODE_NOT_CODED) {
1680                                  pMB->mode = MODE_NOT_CODED;                                  pMB->mode = MODE_NOT_CODED;
1681                                  continue;                                  continue;
1682                          }                          }
1683    
1684                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
1685                            pMB->quant = frame->quant;
1686    
1687  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
1688          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
1689                            skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
1690                          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,  
1691                                                                          &frame->image,                                                                          &frame->image,
1692                                                                          i, j,                                                                          i, j,
1693                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
1694                                                                          TRB, TRD,                                                                          TRB, TRD,
1695                                                                          pParam,                                                                          pParam,
1696                                                                          pMB, b_mb,                                                                          pMB, b_mb,
1697                                                                          &best_sad);                                                                          &best_sad,
1698                                                                            &Data);
1699    
                         if (!(frame->global_flags & XVID_HALFPEL)) best_sad = skip_sad = 256*4096;  
                         else  
1700                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1701    
 //                      best_sad = 256*4096; //uncomment to disable Directsearch.  
 //      To disable any other mode, just comment the function call  
   
1702                          // forward search                          // forward search
1703                          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,
1704                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1705                                                  frame->motion_flags,                                                  frame->motion_flags,
1706                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
1707                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
1708                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
1709    
1710                          // backward search                          // backward search
1711                          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,
1712                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1713                                                  frame->motion_flags,                                                  frame->motion_flags,
1714                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
1715                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
1716                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
1717    
1718                          // 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
1719    
# Line 1354  Line 1723 
1723                                                  i, j,                                                  i, j,
1724                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
1725                                                  frame->motion_flags,                                                  frame->motion_flags,
1726                                                  frame->quant, pParam,                                                  pParam,
1727                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
1728                                                  pMB, &best_sad);                                                  pMB, &best_sad,
1729                                                    &Data);
1730    
1731                          switch (pMB->mode) {                          switch (pMB->mode) {
1732                                  case MODE_FORWARD:                                  case MODE_FORWARD:
1733                                          f_count++;                                          f_count++;
1734                                          f_predMV = pMB->mvs[0];                                          if (pParam->m_quarterpel) f_predMV = pMB->qmvs[0];
1735                                            else f_predMV = pMB->mvs[0];
1736                                          break;                                          break;
1737                                  case MODE_BACKWARD:                                  case MODE_BACKWARD:
1738                                          b_count++;                                          b_count++;
1739                                          b_predMV = pMB->b_mvs[0];                                          if (pParam->m_quarterpel) b_predMV = pMB->b_qmvs[0];
1740                                            else b_predMV = pMB->b_mvs[0];
1741                                          break;                                          break;
1742                                  case MODE_INTERPOLATE:                                  case MODE_INTERPOLATE:
1743                                          i_count++;                                          i_count++;
1744                                            if (pParam->m_quarterpel) {
1745                                                    f_predMV = pMB->qmvs[0];
1746                                                    b_predMV = pMB->b_qmvs[0];
1747                                            } else {
1748                                          f_predMV = pMB->mvs[0];                                          f_predMV = pMB->mvs[0];
1749                                          b_predMV = pMB->b_mvs[0];                                          b_predMV = pMB->b_mvs[0];
1750                                            }
1751                                          break;                                          break;
1752                                  case MODE_DIRECT:                                  case MODE_DIRECT:
1753                                  case MODE_DIRECT_NO4V:                                  case MODE_DIRECT_NO4V:
# Line 1381  Line 1758 
1758                          }                          }
1759                  }                  }
1760          }          }
1761            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);  
   
1762  }  }
1763    
1764  /* Hinted ME starts here */  /* Hinted ME starts here */
1765    
 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));  
 }  
   
   
1766  static void  static void
1767  SearchPhinted ( const uint8_t * const pRef,  SearchPhinted ( const IMAGE * const pRef,
1768                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
1769                                  const uint8_t * const pRefV,                                  const uint8_t * const pRefV,
1770                                  const uint8_t * const pRefHV,                                  const uint8_t * const pRefHV,
# Line 1455  Line 1773 
1773                                  const int y,                                  const int y,
1774                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1775                                  const uint32_t iQuant,                                  const uint32_t iQuant,
                                 const uint32_t iFcode,  
1776                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1777                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1778                                  int inter4v,                                  int inter4v,
1779                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
1780                                    SearchData * const Data)
1781  {  {
1782    
1783          const int32_t iEdgedWidth = pParam->edged_width;          int i, t;
   
         int i;  
         VECTOR currentMV[5];  
         int32_t iMinSAD[5];  
         int32_t temp[5];  
1784          MainSearchFunc * MainSearchPtr;          MainSearchFunc * MainSearchPtr;
         SearchData Data;  
1785    
1786          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,
1787          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);  
1788    
1789          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
1790          Data.iEdgedWidth = iEdgedWidth;          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1791          Data.currentMV = currentMV;          Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1792          Data.iMinSAD = iMinSAD;  
1793          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16;
1794          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
1795          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
1796          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
1797          Data.temp = temp;          Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1798          Data.iQuant = iQuant;          Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1799          Data.iFcode = iFcode;          Data->qpel_precision = 0;
1800    
1801          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
1802                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
1803                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
1804                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
1805                  Data.max_dy = EVEN(Data.max_dy);                  Data->max_dy = EVEN(Data->max_dy);
1806          }          }
1807            if (pParam->m_quarterpel) Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1808            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1809    
1810          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;          for(i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
1811    
1812          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
1813    
1814          if (inter4v)          if (inter4v || Data->chroma) CheckCandidate = CheckCandidate16;
                 CheckCandidate = CheckCandidate16;  
1815          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
1816    
   
1817          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);
1818          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);
1819          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
1820          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;
1821          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;
1822          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;
1823    
1824          CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);          (*CheckCandidate)(pMB->mvs[0].x, pMB->mvs[0].y, 0, &t, Data);
1825    
1826          if (pMB->mode == MODE_INTER4V)          if (pMB->mode == MODE_INTER4V)
1827                  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
1828                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);
1829                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);
1830                          if (!(make_mask(pMB->mvs, i)))                          if (!(make_mask(pMB->mvs, i)))
1831                                  CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);                                  (*CheckCandidate)(pMB->mvs[i].x, pMB->mvs[i].y, 0, &t, Data);
1832                  }                  }
1833    
1834          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1526  Line 1837 
1837                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1838                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1839    
1840          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1841    
1842          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (MotionFlags & PMV_HALFPELREFINE16) SubpelRefine(Data);
1843    
1844          if (inter4v)          for(i = 0; i < 5; i++) {
1845                  for(i = 0; i < 4; i++)                  Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1846                          Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                  Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1847            }
1848    
1849            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1850                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1851                                    pParam->width, pParam->height, Data->iFcode, 0);
1852                    Data->qpel_precision = 1;
1853                    SubpelRefine(Data);
1854            }
1855    
1856            if (inter4v) {
1857                    SearchData Data8;
1858                    Data8.iFcode = Data->iFcode;
1859                    Data8.lambda8 = Data->lambda8;
1860                    Data8.iEdgedWidth = Data->iEdgedWidth;
1861                    Data8.RefQ = Data->RefQ;
1862                    Data8.qpel = Data->qpel;
1863                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1864                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1865                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1866                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1867    
1868                    if (Data->chroma) {
1869                            int sumx, sumy, dx, dy;
1870    
1871                            if(pParam->m_quarterpel) {
1872                                    sumx= pMB->qmvs[0].x/2 + pMB->qmvs[1].x/2 + pMB->qmvs[2].x/2 + pMB->qmvs[3].x/2;
1873                                    sumy = pMB->qmvs[0].y/2 + pMB->qmvs[1].y/2 + pMB->qmvs[2].y/2 + pMB->qmvs[3].y/2;
1874                            } else {
1875                                    sumx = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1876                                    sumy = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1877                            }
1878                            dx = (sumx >> 3) + roundtab_76[sumx & 0xf];
1879                            dy = (sumy >> 3) + roundtab_76[sumy & 0xf];
1880    
1881                            Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);
1882                    }
1883            }
1884    
1885          if (!(inter4v) ||          if (!(inter4v) ||
1886                  (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] +
1887                                                            Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1888  // INTER MODE  // INTER MODE
   
1889                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1890                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1891                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1892    
1893                    pMB->qmvs[0] = pMB->qmvs[1]
1894                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1895    
1896                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1897                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1898    
1899                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1900                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predMV.x;
1901                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predMV.y;
1902          } else {          } else {
1903  // INTER4V MODE; all other things are already set in Search8hinted                          pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1904                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1905                    }
1906            } else {
1907    // INTER4V MODE; all other things are already set in Search8
1908                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1909                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3]
1910                                                    + Data->iMinSAD[4] + IMV16X16 * iQuant;
1911          }          }
1912    
1913  }  }
# Line 1568  Line 1925 
1925          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
1926    
1927          uint32_t x, y;          uint32_t x, y;
1928            uint8_t * qimage;
1929            int32_t temp[5], quant = current->quant;
1930            int32_t iMinSAD[5];
1931            VECTOR currentMV[5], currentQMV[5];
1932            SearchData Data;
1933            Data.iEdgedWidth = pParam->edged_width;
1934            Data.currentMV = currentMV;
1935            Data.currentQMV = currentQMV;
1936            Data.iMinSAD = iMinSAD;
1937            Data.temp = temp;
1938            Data.iFcode = current->fcode;
1939            Data.rounding = pParam->m_rounding_type;
1940            Data.qpel = pParam->m_quarterpel;
1941            Data.chroma = current->global_flags & XVID_ME_COLOUR;
1942    
1943            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
1944                    return; // allocate some mem for qpel interpolated blocks
1945                                      // somehow this is dirty since I think we shouldn't use malloc outside
1946                                      // encoder_create() - so please fix me!
1947    
1948            Data.RefQ = qimage;
1949    
1950          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
1951    
1952          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
1953                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
                         int32_t sad00;  
1954    
1955                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
1956    
# Line 1583  Line 1960 
1960                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
1961                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
1962                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant; }
1963                            else {
1964                                    if (pMB->dquant != NO_CHANGE) {
1965                                            quant += DQtab[pMB->dquant];
1966                                            if (quant > 31) quant = 31;
1967                                            else if (quant < 1) quant = 1;
1968                                    }
1969                                    pMB->quant = quant;
1970                            }
1971    
1972                          if (pMB->dquant == NO_CHANGE) //no skip otherwise, anyway                          SearchPhinted(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
1973                                  sad00 = pMB->sad16                                                          y, current->motion_flags, pMB->quant,
1974                                          = sad16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
1975                                                                  pRef->y + (x + y * pParam->edged_width) * 16,                                                          &Data);
                                                                 pParam->edged_width, 256*4096 );  
                         else sad00 = 256*4096;  
1976    
1977                    }
1978            }
1979            free(qimage);
1980    }
1981    
1982  //initial skip decision  static __inline int
1983    MEanalyzeMB (   const uint8_t * const pRef,
1984                                    const uint8_t * const pCur,
1985                                    const int x,
1986                                    const int y,
1987                                    const MBParam * const pParam,
1988                                    const MACROBLOCK * const pMBs,
1989                                    MACROBLOCK * const pMB,
1990                                    SearchData * const Data)
1991    {
1992    
1993                          if ( (pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)          int i = 255, mask;
1994                                  && ( //(pMB->mode == MODE_NOT_CODED) ||          VECTOR pmv[3];
1995                                          (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant) )) ) {          *(Data->iMinSAD) = MV_MAX_ERROR;
1996                                  if (sad00 < pMB->quant * INITIAL_SKIP_THRESH) {  
1997                                          SkipMacroblockP(pMB, sad00);          //median is only used as prediction. it doesn't have to be real
1998                                          continue; } //skipped          if (x == 1 && y == 1) Data->predMV.x = Data->predMV.y = 0;
1999            else
2000                    if (x == 1) //left macroblock does not have any vector now
2001                            Data->predMV = (pMB - pParam->mb_width)->mvs[0]; // top instead of median
2002                    else if (y == 1) // top macroblock don't have it's vector
2003                            Data->predMV = (pMB - 1)->mvs[0]; // left instead of median
2004                            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); //else median
2005    
2006            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2007                                    pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
2008    
2009            Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
2010            Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
2011    
2012            pmv[1].x = EVEN(pMB->mvs[0].x);
2013            pmv[1].y = EVEN(pMB->mvs[0].y);
2014            pmv[2].x = EVEN(Data->predMV.x);
2015            pmv[2].y = EVEN(Data->predMV.y);
2016            pmv[0].x = pmv[0].y = 0;
2017    
2018            (*CheckCandidate)(0, 0, 255, &i, Data);
2019    
2020    //early skip for 0,0
2021            if (*Data->iMinSAD < MAX_SAD00_FOR_SKIP * 4) {
2022                    pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
2023                    pMB->mode = MODE_NOT_CODED;
2024                    return 0;
2025                          }                          }
                         else sad00 = 256*4096;  
2026    
2027                          if (pMB->mode == MODE_NOT_CODED)          if (!(mask = make_mask(pmv, 1)))
2028                                  SearchP(        pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                  (*CheckCandidate)(pmv[1].x, pmv[1].y, mask, &i, Data);
2029                                                          y, current->motion_flags, pMB->quant,          if (!(mask = make_mask(pmv, 2)))
2030                                                          current->fcode, pParam, pMBs, reference->mbs,                  (*CheckCandidate)(pmv[2].x, pmv[2].y, mask, &i, Data);
2031                                                          current->global_flags & XVID_INTER4V, pMB);  
2032            if (*Data->iMinSAD > MAX_SAD00_FOR_SKIP * 4) // diamond only if needed
2033                    DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
2034    
2035            pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
2036            pMB->mode = MODE_INTER;
2037            return *(Data->iMinSAD);
2038    }
2039    
2040    #define INTRA_THRESH    1350
2041    #define INTER_THRESH    1200
2042    
2043    
2044    int
2045    MEanalysis(     const IMAGE * const pRef,
2046                            FRAMEINFO * const Current,
2047                            MBParam * const pParam,
2048                            int maxIntra, //maximum number if non-I frames
2049                            int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame
2050                            int bCount) // number if B frames in a row
2051    {
2052            uint32_t x, y, intra = 0;
2053            int sSAD = 0;
2054            MACROBLOCK * const pMBs = Current->mbs;
2055            const IMAGE * const pCurrent = &Current->image;
2056            int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH;
2057    
2058            VECTOR currentMV;
2059            int32_t iMinSAD;
2060            SearchData Data;
2061            Data.iEdgedWidth = pParam->edged_width;
2062            Data.currentMV = &currentMV;
2063            Data.iMinSAD = &iMinSAD;
2064            Data.iFcode = Current->fcode;
2065            CheckCandidate = CheckCandidate16no4vI;
2066    
2067            if (intraCount < 10) // we're right after an I frame
2068                    IntraThresh += 4 * (intraCount - 10) * (intraCount - 10);
2069                          else                          else
2070                                  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
2071                                                          y, current->motion_flags, pMB->quant,                          IntraThresh -= (IntraThresh * (maxIntra - 5*(maxIntra - intraCount)))/maxIntra;
                                                         current->fcode, pParam, pMBs,  
                                                         current->global_flags & XVID_INTER4V, pMB);  
2072    
 /* 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);  
2073    
2074            InterThresh += 400 * (1 - bCount);
2075            if (InterThresh < 200) InterThresh = 200;
2076    
2077            if (sadInit) (*sadInit) ();
2078    
2079            for (y = 1; y < pParam->mb_height-1; y++) {
2080                    for (x = 1; x < pParam->mb_width-1; x++) {
2081                            int sad, dev;
2082                            MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2083    
2084                            sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
2085                                                                    pParam, pMBs, pMB, &Data);
2086    
2087                            if (sad > IntraThresh) {
2088                                    dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
2089                                                              pParam->edged_width);
2090                                    if (dev + IntraThresh < sad) {
2091                                            pMB->mode = MODE_INTRA;
2092                                            if (++intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame
2093                                    }
2094                            }
2095                            sSAD += sad;
2096                    }
2097            }
2098            sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2099            if (sSAD > InterThresh ) return 1; //P frame
2100            emms();
2101            return 0; // B frame
2102    
2103    }
2104    
2105    int
2106    FindFcode(      const MBParam * const pParam,
2107                            const FRAMEINFO * const current)
2108    {
2109            uint32_t x, y;
2110            int max = 0, min = 0, i;
2111    
2112            for (y = 0; y < pParam->mb_height; y++) {
2113                    for (x = 0; x < pParam->mb_width; x++) {
2114    
2115                            MACROBLOCK *pMB = &current->mbs[x + y * pParam->mb_width];
2116                            for(i = 0; i < (pMB->mode == MODE_INTER4V ? 4:1); i++) {
2117                                    if (pMB->mvs[i].x > max) max = pMB->mvs[i].x;
2118                                    if (pMB->mvs[i].y > max) max = pMB->mvs[i].y;
2119    
2120                                    if (pMB->mvs[i].x < min) min = pMB->mvs[i].x;
2121                                    if (pMB->mvs[i].y < min) min = pMB->mvs[i].y;
2122                            }
2123                    }
2124            }
2125    
2126            min = -min;
2127            max += 1;
2128            if (min > max) max = min;
2129            if (pParam->m_quarterpel) max *= 2;
2130    
2131            for (i = 1; (max > 32 << (i - 1)); i++);
2132            return i;
2133    }
2134    
2135    static void
2136    CheckGMC(int x, int y, const int dir, int * iDirection,
2137                    const MACROBLOCK * const pMBs, uint32_t * bestcount, VECTOR * GMC,
2138                    const MBParam * const pParam)
2139    {
2140            uint32_t mx, my, a, count = 0;
2141    
2142            for (my = 1; my < pParam->mb_height-1; my++)
2143                    for (mx = 1; mx < pParam->mb_width-1; mx++) {
2144                            VECTOR mv;
2145                            const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2146                            if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED) continue;
2147                            mv = pMB->mvs[0];
2148                            a = ABS(mv.x - x) + ABS(mv.y - y);
2149                            if (a < 6) count += 6 - a;
2150                    }
2151    
2152            if (count > *bestcount) {
2153                    *bestcount = count;
2154                    *iDirection = dir;
2155                    GMC->x = x; GMC->y = y;
2156            }
2157    }
2158    
2159    
2160    static VECTOR
2161    GlobalMotionEst(const MACROBLOCK * const pMBs, const MBParam * const pParam, const uint32_t iFcode)
2162    {
2163    
2164            uint32_t count, bestcount = 0;
2165            int x, y;
2166            VECTOR gmc = {0,0};
2167            int step, min_x, max_x, min_y, max_y;
2168            uint32_t mx, my;
2169            int iDirection, bDirection;
2170    
2171            min_x = min_y = -32<<iFcode;
2172            max_x = max_y = 32<<iFcode;
2173    
2174    //step1: let's find a rough camera panning
2175            for (step = 32; step >= 2; step /= 2) {
2176                    bestcount = 0;
2177                    for (y = min_y; y <= max_y; y += step)
2178                            for (x = min_x ; x <= max_x; x += step) {
2179                                    count = 0;
2180                                    //for all macroblocks
2181                                    for (my = 1; my < pParam->mb_height-1; my++)
2182                                            for (mx = 1; mx < pParam->mb_width-1; mx++) {
2183                                                    const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2184                                                    VECTOR mv;
2185    
2186                                                    if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
2187                                                            continue;
2188    
2189                                                    mv = pMB->mvs[0];
2190                                                    if ( ABS(mv.x - x) <= step && ABS(mv.y - y) <= step )   /* GMC translation is always halfpel-res */
2191                                                            count++;
2192                  }                  }
2193                                    if (count >= bestcount) { bestcount = count; gmc.x = x; gmc.y = y; }
2194          }          }
2195                    min_x = gmc.x - step;
2196                    max_x = gmc.x + step;
2197                    min_y = gmc.y - step;
2198                    max_y = gmc.y + step;
2199    
2200  }  }
2201    
2202            if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10)
2203                    gmc.x = gmc.y = 0; //no camara pan, no GMC
2204    
2205    // step2: let's refine camera panning using gradiend-descent approach.
2206    // TODO: more warping points may be evaluated here (like in interpolate mode search - two vectors in one diamond)
2207            bestcount = 0;
2208            CheckGMC(gmc.x, gmc.y, 255, &iDirection, pMBs, &bestcount, &gmc, pParam);
2209            do {
2210                    x = gmc.x; y = gmc.y;
2211                    bDirection = iDirection; iDirection = 0;
2212                    if (bDirection & 1) CheckGMC(x - 1, y, 1+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2213                    if (bDirection & 2) CheckGMC(x + 1, y, 2+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2214                    if (bDirection & 4) CheckGMC(x, y - 1, 1+2+4, &iDirection, pMBs, &bestcount, &gmc, pParam);
2215                    if (bDirection & 8) CheckGMC(x, y + 1, 1+2+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2216    
2217            } while (iDirection);
2218    
2219            if (pParam->m_quarterpel) {
2220                    gmc.x *= 2;
2221                    gmc.y *= 2;     /* we store the halfpel value as pseudo-qpel to make comparison easier */
2222            }
2223    
2224            return gmc;
2225    }

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

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