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

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

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