[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 700, Sun Dec 8 14:57:09 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 = sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);
312            sad += (data->lambda16 * t * sad)/1000;
313    
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 = lambda_vec16[data->iQuant] *          sad = sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),
330                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);                                          data->iEdgedWidth, 256*4096);
         sad += sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);  
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 530  Line 710 
710    
711          uint32_t x, y;          uint32_t x, y;
712          uint32_t iIntra = 0;          uint32_t iIntra = 0;
713          int32_t InterBias;          int32_t InterBias, quant = current->quant, sad00;
714            uint8_t *qimage;
715    
716            // some pre-initialized thingies for SearchP
717            int32_t temp[5];
718            VECTOR currentMV[5];
719            VECTOR currentQMV[5];
720            int32_t iMinSAD[5];
721            SearchData Data;
722            Data.iEdgedWidth = pParam->edged_width;
723            Data.currentMV = currentMV;
724            Data.currentQMV = currentQMV;
725            Data.iMinSAD = iMinSAD;
726            Data.temp = temp;
727            Data.iFcode = current->fcode;
728            Data.rounding = pParam->m_rounding_type;
729            Data.qpel = pParam->m_quarterpel;
730            Data.chroma = current->global_flags & XVID_ME_COLOUR;
731    
732            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
733                    return 1; // allocate some mem for qpel interpolated blocks
734                                      // somehow this is dirty since I think we shouldn't use malloc outside
735                                      // encoder_create() - so please fix me!
736            Data.RefQ = qimage;
737          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
738    
739          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
740                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
   
741                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
742                          int32_t sad00 =  pMB->sad16  
743                            pMB->sad16
744                                  = sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,                                  = sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,
745                                                          pRef->y + (x + y * pParam->edged_width) * 16,                                                          pRef->y + (x + y * pParam->edged_width) * 16,
746                                                          pParam->edged_width, pMB->sad8 );                                                          pParam->edged_width, pMB->sad8 );
747    
748                            if (Data.chroma) {
749                                    pMB->sad16 += sad8(pCurrent->u + x*8 + y*(pParam->edged_width/2)*8,
750                                                                    pRef->u + x*8 + y*(pParam->edged_width/2)*8, pParam->edged_width/2);
751    
752                                    pMB->sad16 += sad8(pCurrent->v + (x + y*(pParam->edged_width/2))*8,
753                                                                    pRef->v + (x + y*(pParam->edged_width/2))*8, pParam->edged_width/2);
754                            }
755    
756                            sad00 = pMB->sad16; //if no gmc; else sad00 = (..)
757    
758                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
759                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
760                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant;
761                            } else {
762                                    if (pMB->dquant != NO_CHANGE) {
763                                            quant += DQtab[pMB->dquant];
764                                            if (quant > 31) quant = 31;
765                                            else if (quant < 1) quant = 1;
766                                    }
767                                    pMB->quant = quant;
768                            }
769    
770  //initial skip decision  //initial skip decision
771    /* no early skip for GMC (global vector = skip vector is unknown!)  */
772                          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 */
773                                  && (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) ) {                                  if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * INITIAL_SKIP_THRESH)
774                                  if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {                                          if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
775                                                  SkipMacroblockP(pMB, sad00);                                                  SkipMacroblockP(pMB, sad00);
776                                                  continue;                                                  continue;
777                                  }                                  }
778                          } else sad00 = 256*4096; // skip not allowed - for final skip decision                          }
779    
780                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchP(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
781                                                  y, current->motion_flags, pMB->quant,                                                  y, current->motion_flags, pMB->quant,
782                                                  current->fcode, pParam, pMBs, reference->mbs,                                                  &Data, pParam, pMBs, reference->mbs,
783                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
784    
785  /* 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?" */
786                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)                          if (current->coding_type == P_VOP)      {
787                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)                                  if ( (pMB->dquant == NO_CHANGE) && (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)
788                                  { SkipMacroblockP(pMB, sad00); continue; }                                  && ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH) )
789                                            if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
790                                                    SkipMacroblockP(pMB, sad00);
791                                                    continue;
792                                            }
793                            }
794    
795  /* finally, intra decision */  /* finally, intra decision */
796    
797                          InterBias = MV16_INTER_BIAS;                          InterBias = MV16_INTER_BIAS;
798                          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
799                          if (y != 0)                          if (y != 0)
800                                  if ((pMB - pParam->mb_width)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - pParam->mb_width)->mode == MODE_INTRA ) InterBias -= 80;
801                          if (x != 0)                          if (x != 0)
802                                  if ((pMB - 1)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - 1)->mode == MODE_INTRA ) InterBias -= 80;
803    
804                            if (Data.chroma) InterBias += 50; // to compensate bigger SAD
805    
806                          if (InterBias < pMB->sad16)  {                          if (InterBias < pMB->sad16)  {
807                                  const int32_t deviation =                                  const int32_t deviation =
# Line 582  Line 809 
809                                                    pParam->edged_width);                                                    pParam->edged_width);
810    
811                                  if (deviation < (pMB->sad16 - InterBias)) {                                  if (deviation < (pMB->sad16 - InterBias)) {
812                                          if (++iIntra >= iLimit) return 1;                                          if (++iIntra >= iLimit) { free(qimage); return 1; }
813                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
814                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
815                                                  pMB->mvs[3] = zeroMV;                                                  pMB->mvs[3] = zeroMV;
816                                            pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] =
817                                                            pMB->qmvs[3] = zeroMV;
818                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
819                                                  pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
820                                  }                                  }
821                          }                          }
822                  }                  }
823          }          }
824            free(qimage);
825    
826            if (current->coding_type == S_VOP)      /* first GMC step only for S(GMC)-VOPs */
827                    current->GMC_MV = GlobalMotionEst( pMBs, pParam, current->fcode );
828            else
829                    current->GMC_MV = zeroMV;
830    
831          return 0;          return 0;
832  }  }
833    
# Line 601  Line 837 
837  static __inline int  static __inline int
838  make_mask(const VECTOR * const pmv, const int i)  make_mask(const VECTOR * const pmv, const int i)
839  {  {
840          int mask = 0xFF, j;          int mask = 255, j;
841          for (j = 0; j < i; j++) {          for (j = 0; j < i; j++) {
842                  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
843                  if (pmv[i].x == pmv[j].x) {                  if (pmv[i].x == pmv[j].x) {
# Line 625  Line 861 
861    
862          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour
863                  pmv[5].x = EVEN(pmv[3].x);                  pmv[5].x = EVEN(pmv[3].x);
864                  pmv[5].y = EVEN(pmv[3].y); }                  pmv[5].y = EVEN(pmv[3].y);
865          else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
866    
867          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
868          else pmv[3].x = pmv[3].y = 0;          else pmv[3].x = pmv[3].y = 0;
# Line 644  Line 880 
880    
881          if ((x != iWcount-1) && (y != iHcount-1)) {          if ((x != iWcount-1) && (y != iHcount-1)) {
882                  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
883                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y); }                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
884          else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
885  }  }
886    
887  static void  static void
888  SearchP(const uint8_t * const pRef,  SearchP(const IMAGE * const pRef,
889                  const uint8_t * const pRefH,                  const uint8_t * const pRefH,
890                  const uint8_t * const pRefV,                  const uint8_t * const pRefV,
891                  const uint8_t * const pRefHV,                  const uint8_t * const pRefHV,
# Line 658  Line 894 
894                  const int y,                  const int y,
895                  const uint32_t MotionFlags,                  const uint32_t MotionFlags,
896                  const uint32_t iQuant,                  const uint32_t iQuant,
897                  const uint32_t iFcode,                  SearchData * const Data,
898                  const MBParam * const pParam,                  const MBParam * const pParam,
899                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
900                  const MACROBLOCK * const prevMBs,                  const MACROBLOCK * const prevMBs,
# Line 666  Line 902 
902                  MACROBLOCK * const pMB)                  MACROBLOCK * const pMB)
903  {  {
904    
         const int32_t iEdgedWidth = pParam->edged_width;  
   
905          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
906          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);  
   
         Data.predMV = pmv[0];  
         Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
         Data.iEdgedWidth = iEdgedWidth;  
         Data.currentMV = currentMV;  
         Data.iMinSAD = iMinSAD;  
         Data.Ref = pRef + (x + iEdgedWidth*y)*16;  
         Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;  
         Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;  
         Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;  
         Data.temp = temp;  
907    
908          Data.iQuant = iQuant;          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()
909          Data.iFcode = iFcode;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
910                    pParam->width, pParam->height, Data->iFcode - pParam->m_quarterpel);
911    
912            Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
913            Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8;
914            Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8;
915    
916            Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16;
917            Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
918            Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
919            Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
920            Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
921            Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
922    
923            Data->lambda16 = lambda_vec16[iQuant];
924            Data->lambda8 = lambda_vec8[iQuant];
925            Data->qpel_precision = 0;
926    
927          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
928                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
929                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
930                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
931                  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];  
932    
933          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
934    
935            for(i = 0;  i < 5; i++)
936                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
937    
938            if (pParam->m_quarterpel) Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
939            else Data->predMV = pmv[0];
940    
941            i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);
942            Data->iMinSAD[0] = pMB->sad16 + (Data->lambda16 * i * pMB->sad16)/1000;
943            Data->iMinSAD[1] = pMB->sad8[0] + (Data->lambda8 * i * (pMB->sad8[0]+NEIGH_8X8_BIAS))/100;
944            Data->iMinSAD[2] = pMB->sad8[1];
945            Data->iMinSAD[3] = pMB->sad8[2];
946            Data->iMinSAD[4] = pMB->sad8[3];
947    
948          if ((x == 0) && (y == 0)) threshA = 512;          if ((x == 0) && (y == 0)) threshA = 512;
949          else {          else {
950                  threshA = psad[0] + 20;                  threshA = Data->temp[0]; // that's when we keep this SAD atm
951                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
952                  if (threshA > 1024) threshA = 1024; }                  if (threshA > 1024) threshA = 1024; }
953    
954          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,
955                                          prevMBs + x + y * pParam->mb_width);                                          prevMBs + x + y * pParam->mb_width);
956    
957          if (inter4v) CheckCandidate = CheckCandidate16;          if (inter4v || Data->chroma) CheckCandidate = CheckCandidate16;
958          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v; //for extra speed
959    
960  /* main loop. checking all predictions */  /* main loop. checking all predictions */
961    
962          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
963                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
964                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  (*CheckCandidate)(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
965                  if (iMinSAD[0] < threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
966          }          }
967    
968          if ((iMinSAD[0] <= threshA) ||          if ((Data->iMinSAD[0] <= threshA) ||
969                          (MVequal(currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
970                          (iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {                          (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {
971                  inter4v = 0;                  inter4v = 0;
972                  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;  
                 }  
         }  
973    
974          if (MotionFlags & PMV_USESQUARES16)                  MainSearchFunc * MainSearchPtr;
975                  MainSearchPtr = SquareSearch;                  if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
976          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
                 MainSearchPtr = AdvDiamondSearch;  
977                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
978    
979          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, iDirection);                  (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
980    
981  /* extended search, diamond starting in 0,0 and in prediction.  /* extended search, diamond starting in 0,0 and in prediction.
982          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 984 
984    
985          if (MotionFlags & PMV_EXTSEARCH16) {          if (MotionFlags & PMV_EXTSEARCH16) {
986                  int32_t bSAD;                  int32_t bSAD;
987                  VECTOR startMV = Data.predMV, backupMV = currentMV[0];                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
988                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?
989                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);
990                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
991                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
992    
993                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
994                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
995                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
996                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
997                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
998                  }                  }
999    
1000                  backupMV = currentMV[0];                          backupMV = Data->currentMV[0];
1001                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;
1002                  else startMV.x = startMV.y = 0;                  else startMV.x = startMV.y = 0;
1003                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1004                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1005    
1006                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1007                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1008                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1009                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1010                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1011                            }
1012                  }                  }
1013          }          }
1014    
1015  PMVfast16_Terminate_with_Refine:          if (MotionFlags & PMV_HALFPELREFINE16) SubpelRefine(Data);
1016    
1017          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          for(i = 0; i < 5; i++) {
1018                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1019                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1020            }
1021    
1022  PMVfast16_Terminate_without_Refine:          if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1023    
1024                    Data->qpel_precision = 1;
1025                    get_range_qpel(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1026                                    pParam->width, pParam->height, Data->iFcode);
1027    
1028                    SubpelRefine(Data);
1029            }
1030    
1031          if (inter4v)          if (Data->iMinSAD[0] < (int32_t)iQuant * 30 ) inter4v = 0;
1032                  for(i = 0; i < 4; i++)          if (inter4v) {
1033                          Search8(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                  SearchData Data8;
1034                    Data8.iFcode = Data->iFcode;
1035                    Data8.lambda8 = Data->lambda8;
1036                    Data8.iEdgedWidth = Data->iEdgedWidth;
1037                    Data8.RefQ = Data->RefQ;
1038                    Data8.qpel = Data->qpel;
1039                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1040                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1041                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1042                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1043    
1044                    if (Data->chroma) {
1045                            int sumx, sumy, dx, dy;
1046    
1047                            if(pParam->m_quarterpel) {
1048                                    sumx= pMB->qmvs[0].x/2 + pMB->qmvs[1].x/2 + pMB->qmvs[2].x/2 + pMB->qmvs[3].x/2;
1049                                    sumy = pMB->qmvs[0].y/2 + pMB->qmvs[1].y/2 + pMB->qmvs[2].y/2 + pMB->qmvs[3].y/2;
1050                            } else {
1051                                    sumx = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1052                                    sumy = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1053                            }
1054                            dx = (sumx >> 3) + roundtab_76[sumx & 0xf];
1055                            dy = (sumy >> 3) + roundtab_76[sumy & 0xf];
1056    
1057                            Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);
1058                    }
1059            }
1060    
1061          if (!(inter4v) ||          if (!(inter4v) ||
1062                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
1063                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1064  // INTER MODE  // INTER MODE
1065                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1066                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1067                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1068    
1069                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1070                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1071    
1072                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1073                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->qmvs[0] = pMB->qmvs[1]
1074                                    = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1075                            pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predMV.x;
1076                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predMV.y;
1077                    } else {
1078                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1079                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1080                    }
1081          } else {          } else {
1082  // INTER4V MODE; all other things are already set in Search8  // INTER4V MODE; all other things are already set in Search8
1083                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1084                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1085                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1086          }          }
   
1087  }  }
1088    
1089  static void  static void
# Line 820  Line 1093 
1093                  const MBParam * const pParam,                  const MBParam * const pParam,
1094                  MACROBLOCK * const pMB,                  MACROBLOCK * const pMB,
1095                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
1096                  const int block)                  const int block,
1097                    SearchData * const Data)
1098  {  {
1099          SearchData Data;          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1100            Data->currentMV = OldData->currentMV + 1 + block;
1101          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          Data->currentQMV = OldData->currentQMV + 1 + block;
1102          Data.iMinSAD = OldData->iMinSAD + 1 + block;  
1103          Data.currentMV = OldData->currentMV+1+block;          if(pParam->m_quarterpel) {
1104          Data.iFcode = OldData->iFcode;                  Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1105          Data.iQuant = OldData->iQuant;                  if (block != 0) *(Data->iMinSAD) += (Data->lambda8 *
1106                                                                            d_mv_bits(      Data->currentQMV->x - Data->predMV.x,
1107          if (block != 0)                                                                                                  Data->currentQMV->y - Data->predMV.y,
1108                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *                                                                                                  Data->iFcode) * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
1109                                                                  d_mv_bits(      Data.currentMV->x - Data.predMV.x,          } else {
1110                                                                                          Data.currentMV->y - Data.predMV.y,                  Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1111                                                                                          Data.iFcode);                  if (block != 0) *(Data->iMinSAD) += (Data->lambda8 *
1112                                                                            d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1113                                                                                                    Data->currentMV->y - Data->predMV.y,
1114                                                                                                    Data->iFcode) * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
1115            }
1116    
1117          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
1118    
1119                  Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));
1120                  Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));
1121                  Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1122                  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;  
1123    
1124                  Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
1125                    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);  
1126    
1127                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1128                                    pParam->width, pParam->height, OldData->iFcode - pParam->m_quarterpel);
1129                  CheckCandidate = CheckCandidate8;                  CheckCandidate = CheckCandidate8;
1130    
1131                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & PMV_EXTSEARCH8) {
1132                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1133    
1134                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1135                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1136                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1137                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1138    
1139                          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);     }                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1140    
1141                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                          if(*(Data->iMinSAD) < temp_sad) {
1142                                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1143                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1144                            }
1145          }          }
1146    
1147          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;                  if (MotionFlags & PMV_HALFPELREFINE8) {
1148          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;                          int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1149          pMB->mvs[block] = *(Data.currentMV);  
1150          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                          SubpelRefine(Data); // perform halfpel refine of current best vector
1151    
1152                            if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1153                                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1154                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1155                            }
1156                    }
1157    
1158                    if(pParam->m_quarterpel) {
1159                            if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1160                                    (MotionFlags & PMV_QUARTERPELREFINE8)) {
1161                            Data->qpel_precision = 1;
1162                            get_range_qpel(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1163                                    pParam->width, pParam->height, OldData->iFcode);
1164                            SubpelRefine(Data);
1165                            }
1166                    }
1167            }
1168    
1169            if(pParam->m_quarterpel) {
1170                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predMV.x;
1171                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predMV.y;
1172                    pMB->qmvs[block] = *(Data->currentQMV);
1173            }
1174            else {
1175                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1176                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1177            }
1178    
1179            pMB->mvs[block] = *(Data->currentMV);
1180            pMB->sad8[block] =  4 * (*Data->iMinSAD);
1181  }  }
1182    
1183  /* B-frames code starts here */  /* B-frames code starts here */
# Line 896  Line 1205 
1205          pmv[2] = ChoosePred(pMB, mode_curr);          pmv[2] = ChoosePred(pMB, mode_curr);
1206          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);
1207    
         pmv[3].x = pmv[3].y = 0;  
1208          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour
1209                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);
1210                  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);
1211            } else pmv[3].x = pmv[3].y = 0;
1212    
1213          if (y != 0) {          if (y != 0) {
1214                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);
# Line 929  Line 1238 
1238                          const IMAGE * const pCur,                          const IMAGE * const pCur,
1239                          const int x, const int y,                          const int x, const int y,
1240                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
1241                          const uint32_t iFcode,                          const uint32_t iFcode,
1242                          const MBParam * const pParam,                          const MBParam * const pParam,
1243                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
1244                          const VECTOR * const predMV,                          const VECTOR * const predMV,
1245                          int32_t * const best_sad,                          int32_t * const best_sad,
1246                          const int32_t mode_current)                          const int32_t mode_current,
1247                            SearchData * const Data)
1248  {  {
1249    
1250          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1251    
1252          int i, iDirection, mask;          int i, iDirection, mask;
1253          VECTOR currentMV, pmv[7];          VECTOR pmv[7];
1254          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1255          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
1256          SearchData Data;          Data->iFcode = iFcode;
1257            Data->qpel_precision = 0;
1258    
1259          Data.iMinSAD = &iMinSAD;          Data->Ref = pRef + (x + y * iEdgedWidth) * 16;
1260          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->RefH = pRefH + (x + y * iEdgedWidth) * 16;
1261          Data.iEdgedWidth = iEdgedWidth;          Data->RefV = pRefV + (x + y * iEdgedWidth) * 16;
1262          Data.currentMV = &currentMV;          Data->RefHV = pRefHV + (x + y * iEdgedWidth) * 16;
         Data.iMinSAD = &iMinSAD;  
         Data.Ref = pRef + (x + y * iEdgedWidth) * 16;  
         Data.RefH = pRefH + (x + y * iEdgedWidth) * 16;  
         Data.RefV = pRefV + (x + y * iEdgedWidth) * 16;  
         Data.RefHV = pRefHV + (x + y * iEdgedWidth) * 16;  
   
         Data.iQuant = iQuant;  
         Data.iFcode = iFcode;  
         Data.predMV = *predMV;  
1263    
1264          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,          Data->predMV = *predMV;
                                 pParam->width, pParam->height, iFcode);  
1265    
1266          if (!(MotionFlags & PMV_HALFPEL16)) {          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1267                  Data.min_dx = EVEN(Data.min_dx);                                  pParam->width, pParam->height, iFcode - pParam->m_quarterpel);
                 Data.max_dx = EVEN(Data.max_dx);  
                 Data.min_dy = EVEN(Data.min_dy);  
                 Data.max_dy = EVEN(Data.max_dy); } // no-halpel and b-frames. do we need it?  
   
   
         pmv[0] = Data.predMV;  
         PreparePredictionsBF(pmv, x, y, pParam->mb_width,  
                                         pMB, mode_current);  
1268    
1269          currentMV.x = currentMV.y = 0;          pmv[0] = Data->predMV;
1270            if (Data->qpel) { pmv[0].x /= 2; pmv[0].y /= 2; }
1271            PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
1272    
1273            Data->currentMV->x = Data->currentMV->y = 0;
1274          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1275    
1276  // main loop. checking all predictions  // main loop. checking all predictions
1277          for (i = 0; i < 8; i++) {          for (i = 0; i < 8; i++) {
1278                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1279                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1280          }          }
1281    
1282          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 990  Line 1285 
1285                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1286                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1287    
1288          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1289    
1290          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          SubpelRefine(Data);
1291    
1292            if (Data->qpel) {
1293                    Data->currentQMV->x = 2*Data->currentMV->x;
1294                    Data->currentQMV->y = 2*Data->currentMV->y;
1295                    Data->qpel_precision = 1;
1296                    get_range_qpel(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1297                                            pParam->width, pParam->height, iFcode);
1298                    SubpelRefine(Data);
1299            }
1300    
1301  // three bits are needed to code backward mode. four for forward  // three bits are needed to code backward mode. four for forward
1302  // we treat the bits just like they were vector's  // we treat the bits just like they were vector's
1303          if (mode_current == MODE_FORWARD) iMinSAD +=  4 * lambda_vec16[iQuant];          if (mode_current == MODE_FORWARD) *Data->iMinSAD +=  4 * Data->lambda16;
1304          else iMinSAD +=  3 * lambda_vec16[iQuant];          else *Data->iMinSAD +=  3 * Data->lambda16;
1305    
1306            if (*Data->iMinSAD < *best_sad) {
1307          if (iMinSAD < *best_sad) {                  *best_sad = *Data->iMinSAD;
                 *best_sad = iMinSAD;  
1308                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1309                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  if (Data->qpel) {
1310                  pMB->pmvs[0].y = currentMV.y - predMV->y;                          pMB->pmvs[0].x = Data->currentQMV->x - predMV->x;
1311                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                          pMB->pmvs[0].y = Data->currentQMV->y - predMV->y;
1312                  else pMB->b_mvs[0] = currentMV;                          if (mode_current == MODE_FORWARD)
1313                                    pMB->qmvs[0] = *Data->currentQMV;
1314                            else
1315                                    pMB->b_qmvs[0] = *Data->currentQMV;
1316                    } else {
1317                            pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1318                            pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1319                    }
1320                    if (mode_current == MODE_FORWARD)
1321                            pMB->mvs[0] = *(Data->currentMV+2) = *Data->currentMV;
1322                    else
1323                            pMB->b_mvs[0] = *(Data->currentMV+1) = *Data->currentMV; //we store currmv for interpolate search
1324    
1325          }          }
1326    
1327  }  }
1328    
1329  static int32_t  static int32_t
1330  SearchDirect(const uint8_t * const f_Ref,  SearchDirect(const IMAGE * const f_Ref,
1331                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1332                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
1333                                  const uint8_t * const f_RefHV,                                  const uint8_t * const f_RefHV,
1334                                  const uint8_t * const b_Ref,                                  const IMAGE * const b_Ref,
1335                                  const uint8_t * const b_RefH,                                  const uint8_t * const b_RefH,
1336                                  const uint8_t * const b_RefV,                                  const uint8_t * const b_RefV,
1337                                  const uint8_t * const b_RefHV,                                  const uint8_t * const b_RefHV,
1338                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1339                                  const int x, const int y,                                  const int x, const int y,
1340                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1341                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1342                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1343                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1344                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1345                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1346                                    SearchData * const Data)
1347    
1348  {  {
1349          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
         int32_t iMinSAD = 0, skip_sad;  
1350          int k;          int k;
1351          VECTOR currentMV;  
1352          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
         SearchData Data;  
1353    
1354          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;  
1355    
1356          Data.Ref= f_Ref + (x + iEdgedWidth*y) * 16;          Data->Ref = f_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1357          Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;          Data->RefH = f_RefH + (x + Data->iEdgedWidth*y) * 16;
1358          Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;          Data->RefV = f_RefV + (x + Data->iEdgedWidth*y) * 16;
1359          Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = f_RefHV + (x + Data->iEdgedWidth*y) * 16;
1360          Data.bRef = b_Ref + (x + iEdgedWidth*y) * 16;          Data->bRef = b_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1361          Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;          Data->bRefH = b_RefH + (x + Data->iEdgedWidth*y) * 16;
1362          Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;          Data->bRefV = b_RefV + (x + Data->iEdgedWidth*y) * 16;
1363          Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;          Data->bRefHV = b_RefHV + (x + Data->iEdgedWidth*y) * 16;
1364  /*  
1365  //What we do here is a complicated version of CheckCandidateDirect(0,0);          Data->max_dx = 2 * pParam->width - 2 * (x) * 16;
1366  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;
1367            Data->min_dx = -(2 * 16 + 2 * (x) * 16);
1368  */          Data->min_dy = -(2 * 16 + 2 * (y) * 16);
1369          Data.max_dx = 2 * pParam->width - 2 * (x) * 16;          if (Data->qpel) { //we measure in qpixels
1370          Data.max_dy = 2 * pParam->height - 2 * (y) * 16;                  Data->max_dx *= 2;
1371          Data.min_dx = -(2 * 16 + 2 * (x) * 16);                  Data->max_dy *= 2;
1372          Data.min_dy = -(2 * 16 + 2 * (y) * 16);                  Data->min_dx *= 2;
1373                    Data->min_dy *= 2;
1374                    Data->referencemv = b_mb->qmvs;
1375            } else Data->referencemv = b_mb->mvs;
1376            Data->qpel_precision = 0; // it's a trick. it's 1 not 0, but we need 0 here
1377    
1378          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1379                  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);
1380                  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;
1381                  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);
1382                  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; }  
1383    
1384                    if ( ( pMB->b_mvs[k].x > Data->max_dx ) || ( pMB->b_mvs[k].x < Data->min_dx )
1385                            || ( pMB->b_mvs[k].y > Data->max_dy ) || ( pMB->b_mvs[k].y < Data->min_dy )) {
1386    
1387                            *best_sad = 256*4096; // in that case, we won't use direct mode
1388                            pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
1389                            pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;
1390                            return 0;
1391                    }
1392          if (b_mb->mode != MODE_INTER4V) {          if (b_mb->mode != MODE_INTER4V) {
1393                  iMinSAD = sad16bi(Data.Cur,                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1394                                                  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];
1395                                                                  x, y, 16, &pMB->mvs[0], iEdgedWidth),                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1396                                                  get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1397                                                                  x, y, 16, &pMB->b_mvs[0], iEdgedWidth), iEdgedWidth);                          break;
1398                    }
                 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);  
1399          }          }
1400    
1401    
1402            if (b_mb->mode == MODE_INTER4V) CheckCandidate = CheckCandidateDirect;
1403            else CheckCandidate = CheckCandidateDirectno4v;
1404    
1405            (*CheckCandidate)(0, 0, 255, &k, Data);
1406    
1407  // skip decision  // skip decision
1408          if (iMinSAD < (int32_t)iQuant * SKIP_THRESH_B) {          if (*Data->iMinSAD < pMB->quant * SKIP_THRESH_B) {
1409                    //possible skip - checking chroma. everything copied from MC
1410                    //this is not full chroma compensation, only it's fullpel approximation. should work though
1411                    int sum, dx, dy, b_dx, b_dy;
1412    
1413                    if (Data->qpel) {
1414                            sum = pMB->mvs[0].y/2 + pMB->mvs[1].y/2 + pMB->mvs[2].y/2 + pMB->mvs[3].y/2;
1415                            dy = (sum >> 3) + roundtab_76[sum & 0xf];
1416                            sum = pMB->mvs[0].x/2 + pMB->mvs[1].x/2 + pMB->mvs[2].x/2 + pMB->mvs[3].x/2;
1417                            dx = (sum >> 3) + roundtab_76[sum & 0xf];
1418    
1419                            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;
1420                            b_dy = (sum >> 3) + roundtab_76[sum & 0xf];
1421                            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;
1422                            b_dx = (sum >> 3) + roundtab_76[sum & 0xf];
1423    
1424                    } else {
1425                            sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1426                            dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1427                            sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1428                            dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1429    
1430                            sum = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;
1431                            b_dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1432                            sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;
1433                            b_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1434                    }
1435                    sum = sad8bi(pCur->u + 8*x + 8*y*(Data->iEdgedWidth/2),
1436                                            f_Ref->u + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1437                                            b_Ref->u + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1438                                            Data->iEdgedWidth/2);
1439                    sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1440                                            f_Ref->v + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1441                                            b_Ref->v + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1442                                            Data->iEdgedWidth/2);
1443    
1444                    if (sum < MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) {
1445                  pMB->mode = MODE_DIRECT_NONE_MV;                  pMB->mode = MODE_DIRECT_NONE_MV;
1446                  return iMinSAD; }                          return *Data->iMinSAD;
1447                    }
1448            }
1449    
1450          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;  
1451    
1452  //  DIRECT MODE DELTA VECTOR SEARCH.  //  DIRECT MODE DELTA VECTOR SEARCH.
1453  //      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 1456 
1456                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1457                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1458    
1459          (*MainSearchPtr)(0, 0, &Data, 255);          (*MainSearchPtr)(0, 0, Data, 255);
1460    
1461          HalfpelRefine(&Data);          SubpelRefine(Data);
1462    
1463          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
1464          *best_sad = iMinSAD;          *best_sad = *Data->iMinSAD;
1465    
1466          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1467                  pMB->mode = MODE_DIRECT;                  pMB->mode = MODE_DIRECT;
1468          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1469    
1470          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1471    
1472          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1473                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1474                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = (     (Data->currentMV->x == 0)
1475                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1476                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          :pMB->mvs[k].x - Data->referencemv[k].x);
1477                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1478                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1479                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1480                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1481                    if (Data->qpel) {
1482                            pMB->qmvs[k].x = pMB->mvs[k].x; pMB->mvs[k].x /= 2;
1483                            pMB->b_qmvs[k].x = pMB->b_mvs[k].x; pMB->b_mvs[k].x /= 2;
1484                            pMB->qmvs[k].y = pMB->mvs[k].y; pMB->mvs[k].y /= 2;
1485                            pMB->b_qmvs[k].y = pMB->b_mvs[k].y; pMB->b_mvs[k].y /= 2;
1486                    }
1487    
1488                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1489                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1490                          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];
1491                            pMB->qmvs[3] = pMB->qmvs[2] = pMB->qmvs[1] = pMB->qmvs[0];
1492                            pMB->b_qmvs[3] = pMB->b_qmvs[2] = pMB->b_qmvs[1] = pMB->b_qmvs[0];
1493                          break;                          break;
1494                  }                  }
1495          }          }
1496          return 0;//skip_sad;          return skip_sad;
1497  }  }
1498    
1499    
1500  static __inline void  static __inline void
1501  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const uint8_t * const f_Ref,
1502                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
# Line 1168  Line 1511 
1511                                  const uint32_t fcode,                                  const uint32_t fcode,
1512                                  const uint32_t bcode,                                  const uint32_t bcode,
1513                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1514                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1515                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1516                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1517                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1518                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1519                                    SearchData * const fData)
1520    
1521  {  {
 /* 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". */  
1522    
1523          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
   
1524          int iDirection, i, j;          int iDirection, i, j;
1525          int32_t iMinSAD = 256*4096;          SearchData bData;
         VECTOR currentMV[3];  
         SearchData fData, bData;  
1526    
1527            *(bData.iMinSAD = fData->iMinSAD) = 4096*256;
1528            bData.Cur = fData->Cur;
1529            fData->iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;
1530            bData.currentMV = fData->currentMV + 1; bData.currentQMV = fData->currentQMV + 1;
1531            bData.lambda16 = fData->lambda16;
1532            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1533    
1534            bData.bRef = fData->Ref = f_Ref + (x + y * iEdgedWidth) * 16;
1535            bData.bRefH = fData->RefH = f_RefH + (x + y * iEdgedWidth) * 16;
1536            bData.bRefV = fData->RefV = f_RefV + (x + y * iEdgedWidth) * 16;
1537            bData.bRefHV = fData->RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;
1538            bData.Ref = fData->bRef = b_Ref + (x + y * iEdgedWidth) * 16;
1539            bData.RefH = fData->bRefH = b_RefH + (x + y * iEdgedWidth) * 16;
1540            bData.RefV = fData->bRefV = b_RefV + (x + y * iEdgedWidth) * 16;
1541            bData.RefHV = fData->bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;
1542            bData.RefQ = fData->RefQ;
1543            fData->qpel_precision = bData.qpel_precision = 0; bData.qpel = fData->qpel;
1544            bData.rounding = 0;
1545    
1546            bData.bpredMV = fData->predMV = *f_predMV;
1547            fData->bpredMV = bData.predMV = *b_predMV;
1548    
1549            fData->currentMV[0] = fData->currentMV[2];
1550            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);
1551            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);
1552    
1553            if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1554            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dx;
1555            if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dy;
1556            if (fData->currentMV[0].y < fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1557    
1558            if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1559            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dx;
1560            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dy;
1561            if (fData->currentMV[1].y < bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1562    
1563          fData.iMinSAD = bData.iMinSAD = &iMinSAD;          CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
   
         fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
         fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;  
         fData.currentMV = currentMV; bData.currentMV = currentMV + 1;  
         fData.iQuant = bData.iQuant = iQuant;  
         fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;  
   
   
         bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  
         bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;  
         bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;  
         bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;  
         bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;  
         bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;  
         bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;  
         bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;  
   
         bData.bpredMV = fData.predMV = *f_predMV;  
         fData.bpredMV = bData.predMV = *b_predMV;  
   
   
         currentMV[0] = pMB->mvs[0];  
         currentMV[1] = pMB->b_mvs[0];  
         get_range(&fData.min_dx, &fData.max_dx, &fData.min_dy, &fData.max_dy, x, y, 16, pParam->width, pParam->height, fcode);  
         get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode);  
   
         CheckCandidateInt(currentMV[0].x, currentMV[0].y, 255, &iDirection, &fData);  
1564    
1565  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)
1566    
1567          do {          do {
1568                  iDirection = 255;                  iDirection = 255;
1569                  // forward MV moves                  // forward MV moves
1570                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
1571    
1572                  CheckCandidateInt(i + 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1573                  CheckCandidateInt(i, j + 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1574                  CheckCandidateInt(i - 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1575                  CheckCandidateInt(i, j - 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
1576    
1577                  // backward MV moves                  // backward MV moves
1578                  i = currentMV[1].x; j = currentMV[1].y;                  i = fData->currentMV[1].x; j = fData->currentMV[1].y;
1579                  currentMV[2] = currentMV[0];                  fData->currentMV[2] = fData->currentMV[0];
1580                    CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1581                  CheckCandidateInt(i + 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1582                  CheckCandidateInt(i, j + 2, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
1583                  CheckCandidateInt(i - 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, &bData);
                 CheckCandidateInt(i, j - 2, 0, &iDirection, &bData);  
1584    
1585          } while (!(iDirection));          } while (!(iDirection));
1586    
1587  /* halfpel refinement. luckly we can use normal halfpel function for it */          if (fData->qpel) {
   
         if (MotionFlags & PMV_HALFPELREFINE16) {  
1588                  CheckCandidate = CheckCandidateInt;                  CheckCandidate = CheckCandidateInt;
1589                  HalfpelRefine(&fData);                  fData->qpel_precision = bData.qpel_precision = 1;
1590                  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);
1591                  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);
1592          }                  fData->currentQMV[2].x = fData->currentQMV[0].x = 2 * fData->currentMV[0].x;
1593                    fData->currentQMV[2].y = fData->currentQMV[0].y = 2 * fData->currentMV[0].y;
1594  // 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;
1595          iMinSAD +=  2 * lambda_vec16[iQuant];                  fData->currentQMV[1].y = 2 * fData->currentMV[1].y;
1596          if (iMinSAD < *best_sad) {                  SubpelRefine(fData);
1597                  *best_sad = iMinSAD;                  fData->currentQMV[2] = fData->currentQMV[0];
1598                  pMB->mvs[0] = currentMV[0];                  SubpelRefine(&bData);
1599                  pMB->b_mvs[0] = currentMV[1];          }
1600    
1601            *fData->iMinSAD +=  2 * fData->lambda16; // two bits are needed to code interpolate mode.
1602    
1603            if (*fData->iMinSAD < *best_sad) {
1604                    *best_sad = *fData->iMinSAD;
1605                    pMB->mvs[0] = fData->currentMV[0];
1606                    pMB->b_mvs[0] = fData->currentMV[1];
1607                  pMB->mode = MODE_INTERPOLATE;                  pMB->mode = MODE_INTERPOLATE;
1608                    if (fData->qpel) {
1609                            pMB->qmvs[0] = fData->currentQMV[0];
1610                            pMB->b_qmvs[0] = fData->currentQMV[1];
1611                            pMB->pmvs[1].x = pMB->qmvs[0].x - f_predMV->x;
1612                            pMB->pmvs[1].y = pMB->qmvs[0].y - f_predMV->y;
1613                            pMB->pmvs[0].x = pMB->b_qmvs[0].x - b_predMV->x;
1614                            pMB->pmvs[0].y = pMB->b_qmvs[0].y - b_predMV->y;
1615                    } else {
1616                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;
1617                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;
1618                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;
1619                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;
1620          }          }
1621  }  }
1622    }
1623    
1624  void  void
1625  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
# Line 1277  Line 1633 
1633                                           const IMAGE * const f_refV,                                           const IMAGE * const f_refV,
1634                                           const IMAGE * const f_refHV,                                           const IMAGE * const f_refHV,
1635                                           // backward (future) reference                                           // backward (future) reference
1636                                           const MACROBLOCK * const b_mbs,                                           const FRAMEINFO * const b_reference,
1637                                           const IMAGE * const b_ref,                                           const IMAGE * const b_ref,
1638                                           const IMAGE * const b_refH,                                           const IMAGE * const b_refH,
1639                                           const IMAGE * const b_refV,                                           const IMAGE * const b_refV,
# Line 1287  Line 1643 
1643          int32_t best_sad, skip_sad;          int32_t best_sad, skip_sad;
1644          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;
1645          static const VECTOR zeroMV={0,0};          static const VECTOR zeroMV={0,0};
1646            const MACROBLOCK * const b_mbs = b_reference->mbs;
1647    
1648          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
1649    
1650          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1651          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
1652            uint8_t * qimage;
1653    
1654          // note: i==horizontal, j==vertical  // some pre-inintialized data for the rest of the search
1655    
1656            SearchData Data;
1657            int32_t iMinSAD;
1658            VECTOR currentMV[3];
1659            VECTOR currentQMV[3];
1660            Data.iEdgedWidth = pParam->edged_width;
1661            Data.currentMV = currentMV; Data.currentQMV = currentQMV;
1662            Data.iMinSAD = &iMinSAD;
1663            Data.lambda16 = lambda_vec16[frame->quant] + 2;
1664            Data.qpel = pParam->m_quarterpel;
1665            Data.rounding = 0;
1666    
1667            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
1668                    return; // allocate some mem for qpel interpolated blocks
1669                                      // somehow this is dirty since I think we shouldn't use malloc outside
1670                                      // encoder_create() - so please fix me!
1671            Data.RefQ = qimage;
1672    
1673            // note: i==horizontal, j==vertical
1674          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
1675    
1676                  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 1679 
1679                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;
1680                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;
1681    
1682  /* 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 */
1683                            if (b_reference->coding_type != S_VOP)
1684                          if (b_mb->mode == MODE_NOT_CODED) {                          if (b_mb->mode == MODE_NOT_CODED) {
1685                                  pMB->mode = MODE_NOT_CODED;                                  pMB->mode = MODE_NOT_CODED;
1686                                  continue;                                  continue;
1687                          }                          }
1688    
1689                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
1690                            pMB->quant = frame->quant;
1691    
1692  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
1693          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
1694                            skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
1695                          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,  
1696                                                                          &frame->image,                                                                          &frame->image,
1697                                                                          i, j,                                                                          i, j,
1698                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
1699                                                                          TRB, TRD,                                                                          TRB, TRD,
1700                                                                          pParam,                                                                          pParam,
1701                                                                          pMB, b_mb,                                                                          pMB, b_mb,
1702                                                                          &best_sad);                                                                          &best_sad,
1703                                                                            &Data);
1704    
                         if (!(frame->global_flags & XVID_HALFPEL)) best_sad = skip_sad = 256*4096;  
                         else  
1705                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1706    
 //                      best_sad = 256*4096; //uncomment to disable Directsearch.  
 //      To disable any other mode, just comment the function call  
   
1707                          // forward search                          // forward search
1708                          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,
1709                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1710                                                  frame->motion_flags,                                                  frame->motion_flags,
1711                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
1712                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
1713                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
1714    
1715                          // backward search                          // backward search
1716                          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,
1717                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1718                                                  frame->motion_flags,                                                  frame->motion_flags,
1719                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
1720                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
1721                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
1722    
1723                          // 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
1724    
# Line 1354  Line 1728 
1728                                                  i, j,                                                  i, j,
1729                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
1730                                                  frame->motion_flags,                                                  frame->motion_flags,
1731                                                  frame->quant, pParam,                                                  pParam,
1732                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
1733                                                  pMB, &best_sad);                                                  pMB, &best_sad,
1734                                                    &Data);
1735    
1736                          switch (pMB->mode) {                          switch (pMB->mode) {
1737                                  case MODE_FORWARD:                                  case MODE_FORWARD:
1738                                          f_count++;                                          f_count++;
1739                                          f_predMV = pMB->mvs[0];                                          if (pParam->m_quarterpel) f_predMV = pMB->qmvs[0];
1740                                            else f_predMV = pMB->mvs[0];
1741                                          break;                                          break;
1742                                  case MODE_BACKWARD:                                  case MODE_BACKWARD:
1743                                          b_count++;                                          b_count++;
1744                                          b_predMV = pMB->b_mvs[0];                                          if (pParam->m_quarterpel) b_predMV = pMB->b_qmvs[0];
1745                                            else b_predMV = pMB->b_mvs[0];
1746                                          break;                                          break;
1747                                  case MODE_INTERPOLATE:                                  case MODE_INTERPOLATE:
1748                                          i_count++;                                          i_count++;
1749                                            if (pParam->m_quarterpel) {
1750                                                    f_predMV = pMB->qmvs[0];
1751                                                    b_predMV = pMB->b_qmvs[0];
1752                                            } else {
1753                                          f_predMV = pMB->mvs[0];                                          f_predMV = pMB->mvs[0];
1754                                          b_predMV = pMB->b_mvs[0];                                          b_predMV = pMB->b_mvs[0];
1755                                            }
1756                                          break;                                          break;
1757                                  case MODE_DIRECT:                                  case MODE_DIRECT:
1758                                  case MODE_DIRECT_NO4V:                                  case MODE_DIRECT_NO4V:
1759                                          d_count++;                                          d_count++;
                                         break;  
1760                                  default:                                  default:
1761                                          break;                                          break;
1762                          }                          }
1763                  }                  }
1764          }          }
1765            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);  
   
1766  }  }
1767    
1768  /* Hinted ME starts here */  /* Hinted ME starts here */
1769    
 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));  
 }  
   
   
1770  static void  static void
1771  SearchPhinted ( const uint8_t * const pRef,  SearchPhinted ( const IMAGE * const pRef,
1772                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
1773                                  const uint8_t * const pRefV,                                  const uint8_t * const pRefV,
1774                                  const uint8_t * const pRefHV,                                  const uint8_t * const pRefHV,
# Line 1455  Line 1777 
1777                                  const int y,                                  const int y,
1778                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1779                                  const uint32_t iQuant,                                  const uint32_t iQuant,
                                 const uint32_t iFcode,  
1780                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1781                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1782                                  int inter4v,                                  int inter4v,
1783                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
1784                                    SearchData * const Data)
1785  {  {
1786    
1787          const int32_t iEdgedWidth = pParam->edged_width;          int i, t;
   
         int i;  
         VECTOR currentMV[5];  
         int32_t iMinSAD[5];  
         int32_t temp[5];  
1788          MainSearchFunc * MainSearchPtr;          MainSearchFunc * MainSearchPtr;
         SearchData Data;  
1789    
1790          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,
1791          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);  
1792    
1793          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
1794          Data.iEdgedWidth = iEdgedWidth;          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1795          Data.currentMV = currentMV;          Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1796          Data.iMinSAD = iMinSAD;  
1797          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16;
1798          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
1799          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
1800          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
1801          Data.temp = temp;          Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1802          Data.iQuant = iQuant;          Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1803          Data.iFcode = iFcode;          Data->qpel_precision = 0;
1804    
1805          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
1806                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
1807                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
1808                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
1809                  Data.max_dy = EVEN(Data.max_dy);                  Data->max_dy = EVEN(Data->max_dy);
1810          }          }
1811            if (pParam->m_quarterpel) Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1812            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1813    
1814          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;          for(i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
1815    
1816          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
1817    
1818          if (inter4v)          if (inter4v || Data->chroma) CheckCandidate = CheckCandidate16;
                 CheckCandidate = CheckCandidate16;  
1819          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
1820    
   
1821          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);
1822          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);
1823          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
1824          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;
1825          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;
1826          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;
1827    
1828          CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);          (*CheckCandidate)(pMB->mvs[0].x, pMB->mvs[0].y, 0, &t, Data);
1829    
1830          if (pMB->mode == MODE_INTER4V)          if (pMB->mode == MODE_INTER4V)
1831                  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
1832                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);
1833                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);
1834                          if (!(make_mask(pMB->mvs, i)))                          if (!(make_mask(pMB->mvs, i)))
1835                                  CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);                                  (*CheckCandidate)(pMB->mvs[i].x, pMB->mvs[i].y, 0, &t, Data);
1836                  }                  }
1837    
1838          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1526  Line 1841 
1841                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1842                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1843    
1844          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1845    
1846            if (MotionFlags & PMV_HALFPELREFINE16) SubpelRefine(Data);
1847    
1848          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          for(i = 0; i < 5; i++) {
1849                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1850                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1851            }
1852    
1853            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1854                    get_range_qpel(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1855                                    pParam->width, pParam->height, Data->iFcode);
1856                    Data->qpel_precision = 1;
1857                    SubpelRefine(Data);
1858            }
1859    
1860            if (inter4v) {
1861                    SearchData Data8;
1862                    Data8.iFcode = Data->iFcode;
1863                    Data8.lambda8 = Data->lambda8;
1864                    Data8.iEdgedWidth = Data->iEdgedWidth;
1865                    Data8.RefQ = Data->RefQ;
1866                    Data8.qpel = Data->qpel;
1867                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1868                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1869                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1870                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1871    
1872                    if (Data->chroma) {
1873                            int sumx, sumy, dx, dy;
1874    
1875                            if(pParam->m_quarterpel) {
1876                                    sumx= pMB->qmvs[0].x/2 + pMB->qmvs[1].x/2 + pMB->qmvs[2].x/2 + pMB->qmvs[3].x/2;
1877                                    sumy = pMB->qmvs[0].y/2 + pMB->qmvs[1].y/2 + pMB->qmvs[2].y/2 + pMB->qmvs[3].y/2;
1878                            } else {
1879                                    sumx = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1880                                    sumy = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1881                            }
1882                            dx = (sumx >> 3) + roundtab_76[sumx & 0xf];
1883                            dy = (sumy >> 3) + roundtab_76[sumy & 0xf];
1884    
1885          if (inter4v)                          Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);
1886                  for(i = 0; i < 4; i++)                  }
1887                          Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);          }
1888    
1889          if (!(inter4v) ||          if (!(inter4v) ||
1890                  (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] +
1891                                                            Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1892  // INTER MODE  // INTER MODE
   
1893                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1894                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1895                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1896    
1897                    pMB->qmvs[0] = pMB->qmvs[1]
1898                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1899    
1900                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1901                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1902    
1903                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1904                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predMV.x;
1905                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predMV.y;
1906          } else {          } else {
1907  // INTER4V MODE; all other things are already set in Search8hinted                          pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1908                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1909                    }
1910            } else {
1911    // INTER4V MODE; all other things are already set in Search8
1912                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1913                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3]
1914                                                    + Data->iMinSAD[4] + IMV16X16 * iQuant;
1915          }          }
1916    
1917  }  }
# Line 1568  Line 1929 
1929          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
1930    
1931          uint32_t x, y;          uint32_t x, y;
1932            uint8_t * qimage;
1933            int32_t temp[5], quant = current->quant;
1934            int32_t iMinSAD[5];
1935            VECTOR currentMV[5], currentQMV[5];
1936            SearchData Data;
1937            Data.iEdgedWidth = pParam->edged_width;
1938            Data.currentMV = currentMV;
1939            Data.currentQMV = currentQMV;
1940            Data.iMinSAD = iMinSAD;
1941            Data.temp = temp;
1942            Data.iFcode = current->fcode;
1943            Data.rounding = pParam->m_rounding_type;
1944            Data.qpel = pParam->m_quarterpel;
1945            Data.chroma = current->global_flags & XVID_ME_COLOUR;
1946    
1947            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
1948                    return; // allocate some mem for qpel interpolated blocks
1949                                      // somehow this is dirty since I think we shouldn't use malloc outside
1950                                      // encoder_create() - so please fix me!
1951    
1952            Data.RefQ = qimage;
1953    
1954          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
1955    
1956          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
1957                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
                         int32_t sad00;  
1958    
1959                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
1960    
# Line 1583  Line 1964 
1964                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
1965                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
1966                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant; }
1967                            else {
1968                                    if (pMB->dquant != NO_CHANGE) {
1969                                            quant += DQtab[pMB->dquant];
1970                                            if (quant > 31) quant = 31;
1971                                            else if (quant < 1) quant = 1;
1972                                    }
1973                                    pMB->quant = quant;
1974                            }
1975    
1976                          if (pMB->dquant == NO_CHANGE) //no skip otherwise, anyway                          SearchPhinted(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
1977                                  sad00 = pMB->sad16                                                          y, current->motion_flags, pMB->quant,
1978                                          = sad16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
1979                                                                  pRef->y + (x + y * pParam->edged_width) * 16,                                                          &Data);
                                                                 pParam->edged_width, 256*4096 );  
                         else sad00 = 256*4096;  
1980    
1981                    }
1982            }
1983            free(qimage);
1984    }
1985    
1986  //initial skip decision  static __inline int
1987    MEanalyzeMB (   const uint8_t * const pRef,
1988                                    const uint8_t * const pCur,
1989                                    const int x,
1990                                    const int y,
1991                                    const MBParam * const pParam,
1992                                    const MACROBLOCK * const pMBs,
1993                                    MACROBLOCK * const pMB,
1994                                    SearchData * const Data)
1995    {
1996    
1997                          if ( (pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)          int i = 255, mask;
1998                                  && ( //(pMB->mode == MODE_NOT_CODED) ||          VECTOR pmv[3];
1999                                          (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant) )) ) {          *(Data->iMinSAD) = MV_MAX_ERROR;
2000                                  if (sad00 < pMB->quant * INITIAL_SKIP_THRESH) {  
2001                                          SkipMacroblockP(pMB, sad00);          //median is only used as prediction. it doesn't have to be real
2002                                          continue; } //skipped          if (x == 1 && y == 1) Data->predMV.x = Data->predMV.y = 0;
2003            else
2004                    if (x == 1) //left macroblock does not have any vector now
2005                            Data->predMV = (pMB - pParam->mb_width)->mvs[0]; // top instead of median
2006                    else if (y == 1) // top macroblock don't have it's vector
2007                            Data->predMV = (pMB - 1)->mvs[0]; // left instead of median
2008                            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); //else median
2009    
2010            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2011                                    pParam->width, pParam->height, Data->iFcode - pParam->m_quarterpel);
2012    
2013            Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
2014            Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
2015    
2016            pmv[1].x = EVEN(pMB->mvs[0].x);
2017            pmv[1].y = EVEN(pMB->mvs[0].y);
2018            pmv[2].x = EVEN(Data->predMV.x);
2019            pmv[2].y = EVEN(Data->predMV.y);
2020            pmv[0].x = pmv[0].y = 0;
2021    
2022            (*CheckCandidate)(0, 0, 255, &i, Data);
2023    
2024    //early skip for 0,0
2025            if (*Data->iMinSAD < MAX_SAD00_FOR_SKIP * 4) {
2026                    pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
2027                    pMB->mode = MODE_NOT_CODED;
2028                    return 0;
2029                          }                          }
                         else sad00 = 256*4096;  
2030    
2031                          if (pMB->mode == MODE_NOT_CODED)          if (!(mask = make_mask(pmv, 1)))
2032                                  SearchP(        pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                  (*CheckCandidate)(pmv[1].x, pmv[1].y, mask, &i, Data);
2033                                                          y, current->motion_flags, pMB->quant,          if (!(mask = make_mask(pmv, 2)))
2034                                                          current->fcode, pParam, pMBs, reference->mbs,                  (*CheckCandidate)(pmv[2].x, pmv[2].y, mask, &i, Data);
2035                                                          current->global_flags & XVID_INTER4V, pMB);  
2036            if (*Data->iMinSAD > MAX_SAD00_FOR_SKIP * 4) // diamond only if needed
2037                    DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
2038    
2039            pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
2040            pMB->mode = MODE_INTER;
2041            return *(Data->iMinSAD);
2042    }
2043    
2044    #define INTRA_THRESH    1350
2045    #define INTER_THRESH    1200
2046    
2047    
2048    int
2049    MEanalysis(     const IMAGE * const pRef,
2050                            FRAMEINFO * const Current,
2051                            MBParam * const pParam,
2052                            int maxIntra, //maximum number if non-I frames
2053                            int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame
2054                            int bCount) // number if B frames in a row
2055    {
2056            uint32_t x, y, intra = 0;
2057            int sSAD = 0;
2058            MACROBLOCK * const pMBs = Current->mbs;
2059            const IMAGE * const pCurrent = &Current->image;
2060            int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH;
2061    
2062            VECTOR currentMV;
2063            int32_t iMinSAD;
2064            SearchData Data;
2065            Data.iEdgedWidth = pParam->edged_width;
2066            Data.currentMV = &currentMV;
2067            Data.iMinSAD = &iMinSAD;
2068            Data.iFcode = Current->fcode;
2069            CheckCandidate = CheckCandidate16no4vI;
2070    
2071            if (intraCount < 10) // we're right after an I frame
2072                    IntraThresh += 4 * (intraCount - 10) * (intraCount - 10);
2073                          else                          else
2074                                  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
2075                                                          y, current->motion_flags, pMB->quant,                          IntraThresh -= (IntraThresh * (maxIntra - 5*(maxIntra - intraCount)))/maxIntra;
                                                         current->fcode, pParam, pMBs,  
                                                         current->global_flags & XVID_INTER4V, pMB);  
2076    
 /* 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);  
2077    
2078            InterThresh += 400 * (1 - bCount);
2079            if (InterThresh < 200) InterThresh = 200;
2080    
2081            if (sadInit) (*sadInit) ();
2082    
2083            for (y = 1; y < pParam->mb_height-1; y++) {
2084                    for (x = 1; x < pParam->mb_width-1; x++) {
2085                            int sad, dev;
2086                            MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2087    
2088                            sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
2089                                                                    pParam, pMBs, pMB, &Data);
2090    
2091                            if (sad > IntraThresh) {
2092                                    dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
2093                                                              pParam->edged_width);
2094                                    if (dev + IntraThresh < sad) {
2095                                            pMB->mode = MODE_INTRA;
2096                                            if (++intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame
2097                  }                  }
2098          }          }
2099                            sSAD += sad;
2100  }  }
2101            }
2102            sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2103            if (sSAD > InterThresh ) return 1; //P frame
2104            emms();
2105            return 0; // B frame
2106    
2107    }
2108    
2109    int
2110    FindFcode(      const MBParam * const pParam,
2111                            const FRAMEINFO * const current)
2112    {
2113            uint32_t x, y;
2114            int max = 0, min = 0, i;
2115    
2116            for (y = 0; y < pParam->mb_height; y++) {
2117                    for (x = 0; x < pParam->mb_width; x++) {
2118    
2119                            MACROBLOCK *pMB = &current->mbs[x + y * pParam->mb_width];
2120                            for(i = 0; i < (pMB->mode == MODE_INTER4V ? 4:1); i++) {
2121                                    if (pMB->mvs[i].x > max) max = pMB->mvs[i].x;
2122                                    if (pMB->mvs[i].y > max) max = pMB->mvs[i].y;
2123    
2124                                    if (pMB->mvs[i].x < min) min = pMB->mvs[i].x;
2125                                    if (pMB->mvs[i].y < min) min = pMB->mvs[i].y;
2126                            }
2127                    }
2128            }
2129    
2130            min = -min;
2131            max += 1;
2132            if (min > max) max = min;
2133            if (pParam->m_quarterpel) max *= 2;
2134    
2135            for (i = 1; (max > 32 << (i - 1)); i++);
2136            return i;
2137    }
2138    
2139    static void
2140    CheckGMC(int x, int y, const int dir, int * iDirection,
2141                    const MACROBLOCK * const pMBs, uint32_t * bestcount, VECTOR * GMC,
2142                    const MBParam * const pParam)
2143    {
2144            uint32_t mx, my, a, count = 0;
2145    
2146            for (my = 1; my < pParam->mb_height-1; my++)
2147                    for (mx = 1; mx < pParam->mb_width-1; mx++) {
2148                            VECTOR mv;
2149                            const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2150                            if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED) continue;
2151                            mv = pMB->mvs[0];
2152                            a = ABS(mv.x - x) + ABS(mv.y - y);
2153                            if (a < 6) count += 6 - a;
2154                    }
2155    
2156            if (count > *bestcount) {
2157                    *bestcount = count;
2158                    *iDirection = dir;
2159                    GMC->x = x; GMC->y = y;
2160            }
2161    }
2162    
2163    
2164    static VECTOR
2165    GlobalMotionEst(const MACROBLOCK * const pMBs, const MBParam * const pParam, const uint32_t iFcode)
2166    {
2167    
2168            uint32_t count, bestcount = 0;
2169            int x, y;
2170            VECTOR gmc = {0,0};
2171            int step, min_x, max_x, min_y, max_y;
2172            uint32_t mx, my;
2173            int iDirection, bDirection;
2174    
2175            min_x = min_y = -32<<iFcode;
2176            max_x = max_y = 32<<iFcode;
2177    
2178    //step1: let's find a rough camera panning
2179            for (step = 32; step >= 2; step /= 2) {
2180                    bestcount = 0;
2181                    for (y = min_y; y <= max_y; y += step)
2182                            for (x = min_x ; x <= max_x; x += step) {
2183                                    count = 0;
2184                                    //for all macroblocks
2185                                    for (my = 1; my < pParam->mb_height-1; my++)
2186                                            for (mx = 1; mx < pParam->mb_width-1; mx++) {
2187                                                    const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2188                                                    VECTOR mv;
2189    
2190                                                    if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
2191                                                            continue;
2192    
2193                                                    mv = pMB->mvs[0];
2194                                                    if ( ABS(mv.x - x) <= step && ABS(mv.y - y) <= step )   /* GMC translation is always halfpel-res */
2195                                                            count++;
2196                                            }
2197                                    if (count >= bestcount) { bestcount = count; gmc.x = x; gmc.y = y; }
2198                            }
2199                    min_x = gmc.x - step;
2200                    max_x = gmc.x + step;
2201                    min_y = gmc.y - step;
2202                    max_y = gmc.y + step;
2203    
2204            }
2205    
2206            if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10)
2207                    gmc.x = gmc.y = 0; //no camara pan, no GMC
2208    
2209    // step2: let's refine camera panning using gradiend-descent approach.
2210    // TODO: more warping points may be evaluated here (like in interpolate mode search - two vectors in one diamond)
2211            bestcount = 0;
2212            CheckGMC(gmc.x, gmc.y, 255, &iDirection, pMBs, &bestcount, &gmc, pParam);
2213            do {
2214                    x = gmc.x; y = gmc.y;
2215                    bDirection = iDirection; iDirection = 0;
2216                    if (bDirection & 1) CheckGMC(x - 1, y, 1+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2217                    if (bDirection & 2) CheckGMC(x + 1, y, 2+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2218                    if (bDirection & 4) CheckGMC(x, y - 1, 1+2+4, &iDirection, pMBs, &bestcount, &gmc, pParam);
2219                    if (bDirection & 8) CheckGMC(x, y + 1, 1+2+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2220    
2221            } while (iDirection);
2222    
2223            if (pParam->m_quarterpel) {
2224                    gmc.x *= 2;
2225                    gmc.y *= 2;     /* we store the halfpel value as pseudo-qpel to make comparison easier */
2226            }
2227    
2228            return gmc;
2229    }

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

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