[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 769, Sat Jan 11 14:59:24 2003 UTC
# Line 31  Line 31 
31  #include <assert.h>  #include <assert.h>
32  #include <stdio.h>  #include <stdio.h>
33  #include <stdlib.h>  #include <stdlib.h>
34    #include <string.h>     // memcpy
35    #include <math.h>       // lrint
36    
37  #include "../encoder.h"  #include "../encoder.h"
38  #include "../utils/mbfunctions.h"  #include "../utils/mbfunctions.h"
39  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
40  #include "../global.h"  #include "../global.h"
41  #include "../utils/timer.h"  #include "../utils/timer.h"
42    #include "../image/interpolate8x8.h"
43  #include "motion_est.h"  #include "motion_est.h"
44  #include "motion.h"  #include "motion.h"
45  #include "sad.h"  #include "sad.h"
46    #include "../utils/emms.h"
47    
48  #define INITIAL_SKIP_THRESH     (10)  #define INITIAL_SKIP_THRESH     (10)
49  #define FINAL_SKIP_THRESH       (50)  #define FINAL_SKIP_THRESH       (50)
50  #define MAX_SAD00_FOR_SKIP      (20)  #define MAX_SAD00_FOR_SKIP      (20)
51  #define MAX_CHROMA_SAD_FOR_SKIP (18)  #define MAX_CHROMA_SAD_FOR_SKIP (22)
 #define SKIP_THRESH_B (10)  
52    
53  #define CHECK_CANDIDATE(X,Y,D) { \  #define CHECK_CANDIDATE(X,Y,D) { \
54  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }
55    
56  #define iDiamondSize 2  static __inline uint32_t
57    d_mv_bits(int x, int y, const VECTOR pred, const uint32_t iFcode, const int qpel, const int rrv)
 //FILE * debug;  
   
 static __inline int  
 d_mv_bits(int x, int y, const uint32_t iFcode)  
58  {  {
59          int xb, yb;          int xb, yb;
60            x += x * qpel; y += y * qpel;
61            if (rrv) { x = RRV_MV_SCALEDOWN(x); y = RRV_MV_SCALEDOWN(y); }
62            x -= pred.x;
63            y -= pred.y;
64    
65          if (x == 0) xb = 1;          if (x) {
66          else {                  x = ABS(x);
                 if (x < 0) x = -x;  
67                  x += (1 << (iFcode - 1)) - 1;                  x += (1 << (iFcode - 1)) - 1;
68                  x >>= (iFcode - 1);                  x >>= (iFcode - 1);
69                  if (x > 32) x = 32;                  if (x > 32) x = 32;
70                  xb = mvtab[x] + iFcode;                  xb = mvtab[x] + iFcode;
71          }          } else xb = 1;
72    
73          if (y == 0) yb = 1;          if (y) {
74          else {                  y = ABS(y);
                 if (y < 0) y = -y;  
75                  y += (1 << (iFcode - 1)) - 1;                  y += (1 << (iFcode - 1)) - 1;
76                  y >>= (iFcode - 1);                  y >>= (iFcode - 1);
77                  if (y > 32) y = 32;                  if (y > 32) y = 32;
78                  yb = mvtab[y] + iFcode;                  yb = mvtab[y] + iFcode;
79          }          } else yb = 1;
80          return xb + yb;          return xb + yb;
81  }  }
82    
83  /* CHACK_CANDIATE FUNCTIONS START */  static int32_t
84    ChromaSAD(int dx, int dy, const SearchData * const data)
85    {
86            int sad;
87            const uint32_t stride = data->iEdgedWidth/2;
88    
89            if (dx == data->temp[5] && dy == data->temp[6]) return data->temp[7]; //it has been checked recently
90            data->temp[5] = dx; data->temp[6] = dy; // backup
91    
92            switch (((dx & 1) << 1) | (dy & 1))     {
93                    case 0:
94                            dx = dx / 2; dy = dy / 2;
95                            sad = sad8(data->CurU, data->RefCU + dy * stride + dx, stride);
96                            sad += sad8(data->CurV, data->RefCV + dy * stride + dx, stride);
97                            break;
98                    case 1:
99                            dx = dx / 2; dy = (dy - 1) / 2;
100                            sad = sad8bi(data->CurU, data->RefCU + dy * stride + dx, data->RefCU + (dy+1) * stride + dx, stride);
101                            sad += sad8bi(data->CurV, data->RefCV + dy * stride + dx, data->RefCV + (dy+1) * stride + dx, stride);
102                            break;
103                    case 2:
104                            dx = (dx - 1) / 2; dy = dy / 2;
105                            sad = sad8bi(data->CurU, data->RefCU + dy * stride + dx, data->RefCU + dy * stride + dx+1, stride);
106                            sad += sad8bi(data->CurV, data->RefCV + dy * stride + dx, data->RefCV + dy * stride + dx+1, stride);
107                            break;
108                    default:
109                            dx = (dx - 1) / 2; dy = (dy - 1) / 2;
110                            interpolate8x8_halfpel_hv(data->RefQ, data->RefCU + dy * stride + dx, stride, data->rounding);
111                            sad = sad8(data->CurU, data->RefQ, stride);
112    
113                            interpolate8x8_halfpel_hv(data->RefQ, data->RefCV + dy * stride + dx, stride, data->rounding);
114                            sad += sad8(data->CurV, data->RefQ, stride);
115                            break;
116            }
117            data->temp[7] = sad; //backup, part 2
118            return sad;
119    }
120    
121    static __inline const uint8_t *
122    GetReferenceB(const int x, const int y, const uint32_t dir, const SearchData * const data)
123    {
124    //      dir : 0 = forward, 1 = backward
125            switch ( (dir << 2) | ((x&1)<<1) | (y&1) ) {
126                    case 0 : return data->Ref + x/2 + (y/2)*(data->iEdgedWidth);
127                    case 1 : return data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth);
128                    case 2 : return data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth);
129                    case 3 : return data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth);
130                    case 4 : return data->bRef + x/2 + (y/2)*(data->iEdgedWidth);
131                    case 5 : return data->bRefV + x/2 + ((y-1)/2)*(data->iEdgedWidth);
132                    case 6 : return data->bRefH + (x-1)/2 + (y/2)*(data->iEdgedWidth);
133                    default : return data->bRefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth);
134            }
135    }
136    
137    // this is a simpler copy of GetReferenceB, but as it's __inline anyway, we can keep the two separate
138    static __inline const uint8_t *
139    GetReference(const int x, const int y, const SearchData * const data)
140    {
141            switch ( ((x&1)<<1) | (y&1) ) {
142                    case 0 : return data->Ref + x/2 + (y/2)*(data->iEdgedWidth);
143                    case 1 : return data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth);
144                    case 2 : return data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth);
145                    default : return data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth);
146            }
147    }
148    
149    static uint8_t *
150    Interpolate8x8qpel(const int x, const int y, const uint32_t block, const uint32_t dir, const SearchData * const data)
151    {
152    // create or find a qpel-precision reference picture; return pointer to it
153            uint8_t * Reference = data->RefQ + 16*dir;
154            const uint32_t iEdgedWidth = data->iEdgedWidth;
155            const uint32_t rounding = data->rounding;
156            const int halfpel_x = x/2;
157            const int halfpel_y = y/2;
158            const uint8_t *ref1, *ref2, *ref3, *ref4;
159    
160            ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
161            ref1 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
162            switch( ((x&1)<<1) + (y&1) ) {
163            case 0: // pure halfpel position
164                    return (uint8_t *) ref1;
165                    break;
166    
167            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
168                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
169                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
170                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
171                    break;
172    
173            case 2: // x qpel, y halfpel - left or right during qpel refinement
174                    ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
175                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
176                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
177                    break;
178    
179            default: // x and y in qpel resolution - the "corners" (top left/right and
180                             // bottom left/right) during qpel refinement
181                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
182                    ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
183                    ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
184                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
185                    ref3 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
186                    ref4 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
187                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
188                    break;
189            }
190            return Reference;
191    }
192    
193    static uint8_t *
194    Interpolate16x16qpel(const int x, const int y, const uint32_t dir, const SearchData * const data)
195    {
196    // create or find a qpel-precision reference picture; return pointer to it
197            uint8_t * Reference = data->RefQ + 16*dir;
198            const uint32_t iEdgedWidth = data->iEdgedWidth;
199            const uint32_t rounding = data->rounding;
200            const int halfpel_x = x/2;
201            const int halfpel_y = y/2;
202            const uint8_t *ref1, *ref2, *ref3, *ref4;
203    
204            ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
205            switch( ((x&1)<<1) + (y&1) ) {
206            case 0: // pure halfpel position
207                    return (uint8_t *) ref1;
208            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
209                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
210                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
211                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
212                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
213                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
214                    break;
215    
216            case 2: // x qpel, y halfpel - left or right during qpel refinement
217                    ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
218                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
219                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
220                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
221                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
222                    break;
223    
224            default: // x and y in qpel resolution - the "corners" (top left/right and
225                             // bottom left/right) during qpel refinement
226                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
227                    ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
228                    ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
229                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
230                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
231                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
232                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
233                    break;
234            }
235            return Reference;
236    }
237    
238    /* CHECK_CANDIATE FUNCTIONS START */
239    
240  static void  static void
241  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)
242  {  {
243          int32_t * const sad = data->temp;          int t, xc, yc;
 //      static int32_t sad[5];  
         int t;  
244          const uint8_t * Reference;          const uint8_t * Reference;
245            VECTOR * current;
246    
247          if (( x > data->max_dx) || ( x < data->min_dx)          if ( (x > data->max_dx) | (x < data->min_dx)
248                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  | (y > data->max_dy) | (y < data->min_dy) ) return;
249    
250          switch ( ((x&1)<<1) + (y&1) ) {          if (data->qpel_precision) { // x and y are in 1/4 precision
251                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;                  Reference = Interpolate16x16qpel(x, y, 0, data);
252                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  xc = x/2; yc = y/2; //for chroma sad
253                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;                  current = data->currentQMV;
254                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;          } else {
255                    Reference = GetReference(x, y, data);
256                    current = data->currentMV;
257                    xc = x; yc = y;
258          }          }
259            t = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
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])>>10;
264          data->temp[0] += lambda_vec16[data->iQuant] * t;          data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))>>10;
265          data->temp[1] += lambda_vec8[data->iQuant] * t;  
266            if (data->chroma) data->temp[0] += ChromaSAD((xc >> 1) + roundtab_79[xc & 0x3],
267                                                                                                            (yc >> 1) + roundtab_79[yc & 0x3], data);
268    
269            if (data->temp[0] < data->iMinSAD[0]) {
270                    data->iMinSAD[0] = data->temp[0];
271                    current[0].x = x; current[0].y = y;
272                    *dir = Direction; }
273    
274            if (data->temp[1] < data->iMinSAD[1]) {
275                    data->iMinSAD[1] = data->temp[1]; current[1].x = x; current[1].y= y; }
276            if (data->temp[2] < data->iMinSAD[2]) {
277                    data->iMinSAD[2] = data->temp[2]; current[2].x = x; current[2].y = y; }
278            if (data->temp[3] < data->iMinSAD[3]) {
279                    data->iMinSAD[3] = data->temp[3]; current[3].x = x; current[3].y = y; }
280            if (data->temp[4] < data->iMinSAD[4]) {
281                    data->iMinSAD[4] = data->temp[4]; current[4].x = x; current[4].y = y; }
282    
283    }
284    
285    static void
286    CheckCandidate32(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
287    {
288            uint32_t t;
289            const uint8_t * Reference;
290    
291            if ( (!(x&1) && x !=0) | (!(y&1) && y !=0) || //non-zero integer value
292                    (x > data->max_dx) | (x < data->min_dx)
293                    | (y > data->max_dy) | (y < data->min_dy) ) return;
294    
295            Reference = GetReference(x, y, data);
296            t = d_mv_bits(x, y, data->predMV, data->iFcode, 0, 1);
297    
298            data->temp[0] = sad32v_c(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
299    
300            data->temp[0] += (data->lambda16 * t * data->temp[0]) >> 10;
301            data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))>>10;
302    
303          if (data->temp[0] < data->iMinSAD[0]) {          if (data->temp[0] < data->iMinSAD[0]) {
304                  data->iMinSAD[0] = data->temp[0];                  data->iMinSAD[0] = data->temp[0];
# Line 118  Line 313 
313                  data->iMinSAD[3] = data->temp[3]; data->currentMV[3].x = x; data->currentMV[3].y = y; }                  data->iMinSAD[3] = data->temp[3]; data->currentMV[3].x = x; data->currentMV[3].y = y; }
314          if (data->temp[4] < data->iMinSAD[4]) {          if (data->temp[4] < data->iMinSAD[4]) {
315                  data->iMinSAD[4] = data->temp[4]; data->currentMV[4].x = x; data->currentMV[4].y = y; }                  data->iMinSAD[4] = data->temp[4]; data->currentMV[4].x = x; data->currentMV[4].y = y; }
   
316  }  }
317    
318  static void  static void
# Line 126  Line 320 
320  {  {
321          int32_t sad;          int32_t sad;
322          const uint8_t * Reference;          const uint8_t * Reference;
323            uint32_t t;
324            VECTOR * current;
325    
326          if (( x > data->max_dx) || ( x < data->min_dx)          if ( (x > data->max_dx) | ( x < data->min_dx)
327                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  | (y > data->max_dy) | (y < data->min_dy) ) return;
328    
329          switch ( ((x&1)<<1) + (y&1) )          if (data->rrv && (!(x&1) && x !=0) | (!(y&1) && y !=0) ) return; //non-zero even value
330          {  
331                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;          if (data->qpel_precision) { // x and y are in 1/4 precision
332                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  Reference = Interpolate16x16qpel(x, y, 0, data);
333                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;                  current = data->currentQMV;
334                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;          } else {
335                    Reference = GetReference(x, y, data);
336                    current = data->currentMV;
337          }          }
338            t = d_mv_bits(x, y, data->predMV, data->iFcode,
339                                            data->qpel^data->qpel_precision, data->rrv);
340    
341          sad = lambda_vec16[data->iQuant] *          sad = sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);
342                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          sad += (data->lambda16 * t * sad)>>10;
         sad += sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);  
343    
344          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
345                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
346                    current->x = x; current->y = y;
347                    *dir = Direction; }
348    }
349    
350    static void
351    CheckCandidate32I(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
352    {
353    // maximum speed - for P/B/I decision
354    
355            if ( (x > data->max_dx) | (x < data->min_dx)
356                    | (y > data->max_dy) | (y < data->min_dy) ) return;
357    
358            data->temp[0] = sad32v_c(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),
359                                                            data->iEdgedWidth, data->temp+1);
360    
361            if (data->temp[0] < *(data->iMinSAD)) {
362                    *(data->iMinSAD) = data->temp[0];
363                  data->currentMV[0].x = x; data->currentMV[0].y = y;                  data->currentMV[0].x = x; data->currentMV[0].y = y;
364                  *dir = Direction; }                  *dir = Direction; }
365            if (data->temp[1] < data->iMinSAD[1]) {
366                    data->iMinSAD[1] = data->temp[1]; data->currentMV[1].x = x; data->currentMV[1].y = y; }
367            if (data->temp[2] < data->iMinSAD[2]) {
368                    data->iMinSAD[2] = data->temp[2]; data->currentMV[2].x = x; data->currentMV[2].y = y; }
369            if (data->temp[3] < data->iMinSAD[3]) {
370                    data->iMinSAD[3] = data->temp[3]; data->currentMV[3].x = x; data->currentMV[3].y = y; }
371            if (data->temp[4] < data->iMinSAD[4]) {
372                    data->iMinSAD[4] = data->temp[4]; data->currentMV[4].x = x; data->currentMV[4].y = y; }
373    
374  }  }
375    
376  static void  static void
377  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)
378  {  {
379          int32_t sad;          int32_t sad, xb, yb;
380          const int xb = data->currentMV[1].x;          uint32_t t;
         const int yb = data->currentMV[1].y;  
381          const uint8_t *ReferenceF, *ReferenceB;          const uint8_t *ReferenceF, *ReferenceB;
382            VECTOR *current;
383    
384          if (( xf > data->max_dx) || ( xf < data->min_dx)          if ( (xf > data->max_dx) | (xf < data->min_dx)
385                  || ( yf > data->max_dy) || (yf < data->min_dy)) return;                  | (yf > data->max_dy) | (yf < data->min_dy) ) return;
386    
387          switch ( ((xf&1)<<1) + (yf&1) ) {          if (!data->qpel_precision) {
388                  case 0 : ReferenceF = data->Ref + xf/2 + (yf/2)*(data->iEdgedWidth); break;                  ReferenceF = GetReference(xf, yf, data);
389                  case 1 : ReferenceF = data->RefV + xf/2 + ((yf-1)/2)*(data->iEdgedWidth); break;                  xb = data->currentMV[1].x; yb = data->currentMV[1].y;
390                  case 2 : ReferenceF = data->RefH + (xf-1)/2 + (yf/2)*(data->iEdgedWidth); break;                  ReferenceB = GetReferenceB(xb, yb, 1, data);
391                  default : ReferenceF = data->RefHV + (xf-1)/2 + ((yf-1)/2)*(data->iEdgedWidth); break;                  current = data->currentMV;
392          }          } else {
393                    ReferenceF = Interpolate16x16qpel(xf, yf, 0, data);
394          switch ( ((xb&1)<<1) + (yb&1) ) {                  xb = data->currentQMV[1].x; yb = data->currentQMV[1].y;
395                  case 0 : ReferenceB = data->bRef + xb/2 + (yb/2)*(data->iEdgedWidth); break;                  current = data->currentQMV;
396                  case 1 : ReferenceB = data->bRefV + xb/2 + ((yb-1)/2)*(data->iEdgedWidth); break;                  ReferenceB = Interpolate16x16qpel(xb, yb, 1, data);
                 case 2 : ReferenceB = data->bRefH + (xb-1)/2 + (yb/2)*(data->iEdgedWidth); break;  
                 default : ReferenceB = data->bRefHV + (xb-1)/2 + ((yb-1)/2)*(data->iEdgedWidth); break;  
397          }          }
398    
399          sad = lambda_vec16[data->iQuant] *          t = d_mv_bits(xf, yf, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0)
400                          ( d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode) +                   + d_mv_bits(xb, yb, data->bpredMV, data->iFcode, data->qpel^data->qpel_precision, 0);
                           d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode) );  
401    
402          sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
403            sad += (data->lambda16 * t * sad)>>10;
404    
405          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
406                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
407                  data->currentMV->x = xf; data->currentMV->y = yf;                  current->x = xf; current->y = yf;
408                  *dir = Direction; }                  *dir = Direction; }
409  }  }
410    
411  static void  static void
412  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)
413  {  {
414          int32_t sad;          int32_t sad = 0;
415          int k;          uint32_t k;
416          const uint8_t *ReferenceF;          const uint8_t *ReferenceF;
417          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
418          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
419    
420          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;          if (( x > 31) | ( x < -32) | ( y > 31) | (y < -32)) return;
   
         sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);  
421    
422          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
423                  mvs.x = data->directmvF[k].x + x;                  mvs.x = data->directmvF[k].x + x;
# Line 214  Line 435 
435                          || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )                          || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )
436                          || ( 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;
437    
                 switch ( ((mvs.x&1)<<1) + (mvs.y&1) ) {  
                         case 0 : ReferenceF = data->Ref + mvs.x/2 + (mvs.y/2)*(data->iEdgedWidth); break;  
                         case 1 : ReferenceF = data->RefV + mvs.x/2 + ((mvs.y-1)/2)*(data->iEdgedWidth); break;  
                         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;  
                 }  
438    
439                  switch ( ((b_mvs.x&1)<<1) + (b_mvs.y&1) ) {                  mvs.x *= 2 - data->qpel; mvs.y *= 2 - data->qpel;
440                          case 0 : ReferenceB = data->bRef + b_mvs.x/2 + (b_mvs.y/2)*(data->iEdgedWidth); break;                  b_mvs.x *= 2 - data->qpel; b_mvs.y *= 2 - data->qpel; //we move to qpel precision anyway
441                          case 1 : ReferenceB = data->bRefV + b_mvs.x/2 + ((b_mvs.y-1)/2)*(data->iEdgedWidth); break;  
442                          case 2 : ReferenceB = data->bRefH + (b_mvs.x-1)/2 + (b_mvs.y/2)*(data->iEdgedWidth); break;                  ReferenceF = Interpolate8x8qpel(mvs.x, mvs.y, k, 0, data);
443                          default : ReferenceB = data->bRefHV + (b_mvs.x-1)/2 + ((b_mvs.y-1)/2)*(data->iEdgedWidth); break;                  ReferenceB = Interpolate8x8qpel(b_mvs.x, b_mvs.y, k, 1, data);
                 }  
444    
445                  sad += sad8bi(data->Cur + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),                  sad += sad8bi(data->Cur + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
446                                                  ReferenceF + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),                                                  ReferenceF, ReferenceB, data->iEdgedWidth);
                                                 ReferenceB + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),  
                                                 data->iEdgedWidth);  
447                  if (sad > *(data->iMinSAD)) return;                  if (sad > *(data->iMinSAD)) return;
448          }          }
449    
450            sad += (data->lambda16 * d_mv_bits(x, y, zeroMV, 1, 0, 0) * sad)>>10;
451    
452          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
453                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
454                  data->currentMV->x = x; data->currentMV->y = y;                  data->currentMV->x = x; data->currentMV->y = y;
# Line 249  Line 463 
463          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
464          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
465    
466          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);  
467    
468          mvs.x = data->directmvF[0].x + x;          mvs.x = data->directmvF[0].x + x;
469          b_mvs.x = ((x == 0) ?          b_mvs.x = ((x == 0) ?
# Line 268  Line 480 
480                  || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )                  || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )
481                  || ( 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;
482    
483          switch ( ((mvs.x&1)<<1) + (mvs.y&1) ) {          mvs.x *= 2 - data->qpel; mvs.y *= 2 - data->qpel;
484                  case 0 : ReferenceF = data->Ref + mvs.x/2 + (mvs.y/2)*(data->iEdgedWidth); break;          b_mvs.x *= 2 - data->qpel; b_mvs.y *= 2 - data->qpel; //we move to qpel precision anyway
                 case 1 : ReferenceF = data->RefV + mvs.x/2 + ((mvs.y-1)/2)*(data->iEdgedWidth); break;  
                 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;  
         }  
485    
486          switch ( ((b_mvs.x&1)<<1) + (b_mvs.y&1) ) {          ReferenceF = Interpolate16x16qpel(mvs.x, mvs.y, 0, data);
487                  case 0 : ReferenceB = data->bRef + b_mvs.x/2 + (b_mvs.y/2)*(data->iEdgedWidth); break;          ReferenceB = Interpolate16x16qpel(b_mvs.x, b_mvs.y, 1, data);
                 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;  
         }  
488    
489          sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
490            sad += (data->lambda16 * d_mv_bits(x, y, zeroMV, 1, 0, 0) * sad)>>10;
491    
492          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
493                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 293  Line 498 
498  static void  static void
499  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)
500  {  {
501          int32_t sad;          int32_t sad; uint32_t t;
502          const uint8_t * Reference;          const uint8_t * Reference;
503    
504          if (( x > data->max_dx) || ( x < data->min_dx)          if ( (x > data->max_dx) | (x < data->min_dx)
505                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  | (y > data->max_dy) | (y < data->min_dy) ) return;
506    
507          switch ( ((x&1)<<1) + (y&1) )          if (data->qpel) Reference = Interpolate16x16qpel(x, y, 0, data);
508          {          else Reference = GetReference(x, y, 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;  
         }  
509    
510          sad = sad8(data->Cur, Reference, data->iEdgedWidth);          sad = sad8(data->Cur, Reference, data->iEdgedWidth);
511          sad += lambda_vec8[data->iQuant] * d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          t = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel && !data->qpel_precision, 0);
512    
513            sad += (data->lambda8 * t * (sad+NEIGH_8X8_BIAS))>>10;
514    
515          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
516                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 316  Line 518 
518                  *dir = Direction; }                  *dir = Direction; }
519  }  }
520    
521  /* CHACK_CANDIATE FUNCTIONS END */  /* CHECK_CANDIATE FUNCTIONS END */
522    
523  /* MAINSEARCH FUNCTIONS START */  /* MAINSEARCH FUNCTIONS START */
524    
# Line 328  Line 530 
530    
531                  int iDirection;                  int iDirection;
532    
533                  do {          for(;;) { //forever
534                          iDirection = 0;                          iDirection = 0;
535                          if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);                          if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);
536                          if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);                          if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);
# Line 337  Line 539 
539    
540                          /* now we're doing diagonal checks near our candidate */                          /* now we're doing diagonal checks near our candidate */
541    
542                          if (iDirection) {               //checking if anything found                  if (iDirection) {               //if anything found
543                                  bDirection = iDirection;                                  bDirection = iDirection;
544                                  iDirection = 0;                                  iDirection = 0;
545                                  x = data->currentMV->x; y = data->currentMV->y;                                  x = data->currentMV->x; y = data->currentMV->y;
# Line 346  Line 548 
548                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);
549                                  } else {                        // what remains here is up or down                                  } else {                        // what remains here is up or down
550                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);
551                                          CHECK_CANDIDATE(x - iDiamondSize, y, 1); }                                  CHECK_CANDIDATE(x - iDiamondSize, y, 1);
552                            }
553    
554                                  if (iDirection) {                                  if (iDirection) {
555                                          bDirection += iDirection;                                          bDirection += iDirection;
556                                          x = data->currentMV->x; y = data->currentMV->y; }                                  x = data->currentMV->x; y = data->currentMV->y;
557                            }
558                          } else {                                //about to quit, eh? not so fast....                          } else {                                //about to quit, eh? not so fast....
559                                  switch (bDirection) {                                  switch (bDirection) {
560                                  case 2:                                  case 2:
# Line 401  Line 605 
605                                  x = data->currentMV->x; y = data->currentMV->y;                                  x = data->currentMV->x; y = data->currentMV->y;
606                          }                          }
607                  }                  }
                 while (1);                              //forever  
608  }  }
609    
610  static void  static void
# Line 451  Line 654 
654                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);
655                                  } else {                        // what remains here is up or down                                  } else {                        // what remains here is up or down
656                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);
657                                          CHECK_CANDIDATE(x - iDiamondSize, y, 1); }                                  CHECK_CANDIDATE(x - iDiamondSize, y, 1);
658                            }
659                                  bDirection += iDirection;                                  bDirection += iDirection;
660                                  x = data->currentMV->x; y = data->currentMV->y;                                  x = data->currentMV->x; y = data->currentMV->y;
661                          }                          }
# Line 462  Line 665 
665    
666  /* MAINSEARCH FUNCTIONS END */  /* MAINSEARCH FUNCTIONS END */
667    
 /* HALFPELREFINE COULD BE A MAINSEARCH FUNCTION, BUT THERE IS NO NEED FOR IT */  
   
668  static void  static void
669  HalfpelRefine(const SearchData * const data)  SubpelRefine(const SearchData * const data)
670  {  {
671  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a half-pel or q-pel refinement */
672            const VECTOR centerMV = data->qpel_precision ? *data->currentQMV : *data->currentMV;
673          VECTOR backupMV = *(data->currentMV);          int iDirection; //only needed because macro expects it
674          int iDirection; //not needed  
675            CHECK_CANDIDATE(centerMV.x, centerMV.y - 1, 0);
676          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);          CHECK_CANDIDATE(centerMV.x + 1, centerMV.y - 1, 0);
677          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);          CHECK_CANDIDATE(centerMV.x + 1, centerMV.y, 0);
678          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);          CHECK_CANDIDATE(centerMV.x + 1, centerMV.y + 1, 0);
679          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y + 1, 0);          CHECK_CANDIDATE(centerMV.x, centerMV.y + 1, 0);
680            CHECK_CANDIDATE(centerMV.x - 1, centerMV.y + 1, 0);
681          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y, 0);          CHECK_CANDIDATE(centerMV.x - 1, centerMV.y, 0);
682          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y, 0);          CHECK_CANDIDATE(centerMV.x - 1, centerMV.y - 1, 0);
   
         CHECK_CANDIDATE(backupMV.x, backupMV.y + 1, 0);  
         CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);  
683  }  }
684    
685  static __inline int  static __inline int
686  SkipDecisionP(const IMAGE * current, const IMAGE * reference,  SkipDecisionP(const IMAGE * current, const IMAGE * reference,
687                                                          const int x, const int y,                                                          const int x, const int y,
688                                                          const uint32_t iEdgedWidth, const uint32_t iQuant)                                                          const uint32_t stride, const uint32_t iQuant, int rrv)
689    
690  {  {
691  /*      keep repeating checks for all b-frames before this P frame,          if(!rrv) {
692          to make sure that SKIP is possible (todo)                  uint32_t sadC = sad8(current->u + x*8 + y*stride*8,
693          how: if skip is not possible set sad00 to a very high value */                                                  reference->u + x*8 + y*stride*8, stride);
   
         uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,  
                                         reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);  
694          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
695          sadC += sad8(current->v + x*8 + y*(iEdgedWidth/2)*8,                  sadC += sad8(current->v + (x + y*stride)*8,
696                                          reference->v + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                                  reference->v + (x + y*stride)*8, stride);
697          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
698                    return 1;
699    
700            } else {
701                    uint32_t sadC = sad16(current->u + x*16 + y*stride*16,
702                                                    reference->u + x*16 + y*stride*16, stride, 256*4096);
703                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP*4) return 0;
704                    sadC += sad16(current->v + (x + y*stride)*16,
705                                                    reference->v + (x + y*stride)*16, stride, 256*4096);
706                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP*4) return 0;
707          return 1;          return 1;
708  }  }
709    }
710    
711  static __inline void  static __inline void
712  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)
713  {  {
714          pMB->mode = MODE_NOT_CODED;          pMB->mode = MODE_NOT_CODED;
715          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = pMB->mv16.x = 0;          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = zeroMV;
716          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = pMB->mv16.y = 0;          pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] = pMB->qmvs[3] = zeroMV;
717          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;
718  }  }
719    
# Line 526  Line 730 
730          const IMAGE *const pCurrent = &current->image;          const IMAGE *const pCurrent = &current->image;
731          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
732    
733          const VECTOR zeroMV = { 0, 0 };          uint32_t mb_width = pParam->mb_width;
734            uint32_t mb_height = pParam->mb_height;
735            const uint32_t iEdgedWidth = pParam->edged_width;
736    
737          uint32_t x, y;          uint32_t x, y;
738          uint32_t iIntra = 0;          uint32_t iIntra = 0;
739          int32_t InterBias;          int32_t InterBias, quant = current->quant, sad00;
740    
741          if (sadInit) (*sadInit) ();          // some pre-initialized thingies for SearchP
742            int32_t temp[8];
743            VECTOR currentMV[5];
744            VECTOR currentQMV[5];
745            int32_t iMinSAD[5];
746            SearchData Data;
747            memset(&Data, 0, sizeof(SearchData));
748            Data.iEdgedWidth = iEdgedWidth;
749            Data.currentMV = currentMV;
750            Data.currentQMV = currentQMV;
751            Data.iMinSAD = iMinSAD;
752            Data.temp = temp;
753            Data.iFcode = current->fcode;
754            Data.rounding = pParam->m_rounding_type;
755            Data.qpel = pParam->m_quarterpel;
756            Data.chroma = current->global_flags & ( PMV_CHROMA16 | PMV_CHROMA8 );
757            Data.rrv = current->global_flags & XVID_REDUCED;
758    
759            if ((current->global_flags & XVID_REDUCED)) {
760                    mb_width = (pParam->width + 31) / 32;
761                    mb_height = (pParam->height + 31) / 32;
762                    Data.qpel = Data.chroma = 0;
763            }
764    
765          for (y = 0; y < pParam->mb_height; y++) {          Data.RefQ = pRefV->u; // a good place, also used in MC (for similar purpose)
766                  for (x = 0; x < pParam->mb_width; x++)  {          if (sadInit) (*sadInit) ();
767    
768            for (y = 0; y < mb_height; y++) {
769                    for (x = 0; x < mb_width; x++)  {
770                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
771                          int32_t sad00 =  pMB->sad16  
772                                  = sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,                          if (!Data.rrv) pMB->sad16 =
773                                                          pRef->y + (x + y * pParam->edged_width) * 16,                                  sad16v(pCurrent->y + (x + y * iEdgedWidth) * 16,
774                                                            pRef->y + (x + y * iEdgedWidth) * 16,
775                                                          pParam->edged_width, pMB->sad8 );                                                          pParam->edged_width, pMB->sad8 );
776    
777                            else pMB->sad16 =
778                                    sad32v_c(pCurrent->y + (x + y * iEdgedWidth) * 32,
779                                                            pRef->y + (x + y * iEdgedWidth) * 32,
780                                                            pParam->edged_width, pMB->sad8 );
781    
782                            if (Data.chroma) {
783                                    Data.temp[7] = sad8(pCurrent->u + x*8 + y*(iEdgedWidth/2)*8,
784                                                                            pRef->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2)
785                                                                    + sad8(pCurrent->v + (x + y*(iEdgedWidth/2))*8,
786                                                                            pRef->v + (x + y*(iEdgedWidth/2))*8, iEdgedWidth/2);
787                                    pMB->sad16 += Data.temp[7];
788                            }
789    
790                            sad00 = pMB->sad16;
791    
792                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
793                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
794                                  pMB->quant = current->quant; }                          } else {
795                                    if (pMB->dquant != NO_CHANGE) {
796                                            quant += DQtab[pMB->dquant];
797                                            if (quant > 31) quant = 31;
798                                            else if (quant < 1) quant = 1;
799                                    }
800                            }
801                            pMB->quant = current->quant;
802    
803  //initial skip decision  //initial skip decision
804    /* no early skip for GMC (global vector = skip vector is unknown!)  */
805                          if ((pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)                          if (!(current->global_flags & XVID_GMC))        { /* no fast SKIP for S(GMC)-VOPs */
806                                  && (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) ) {                                  if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * INITIAL_SKIP_THRESH  * (Data.rrv ? 4:1) )
807                                  if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {                                          if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, iEdgedWidth/2, pMB->quant, Data.rrv)) {
808                                                  SkipMacroblockP(pMB, sad00);                                                  SkipMacroblockP(pMB, sad00);
809                                                  continue;                                                  continue;
810                                  }                                  }
811                          } else sad00 = 256*4096; // skip not allowed - for final skip decision                          }
812    
813                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchP(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
814                                                  y, current->motion_flags, pMB->quant,                                                  y, current->motion_flags, pMB->quant,
815                                                  current->fcode, pParam, pMBs, reference->mbs,                                                  &Data, pParam, pMBs, reference->mbs,
816                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
817    
818  /* 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?" */
819                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)                          if (!(current->global_flags & XVID_GMC))        {
820                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)                                  if ( (pMB->dquant == NO_CHANGE) && (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)
821                                  { SkipMacroblockP(pMB, sad00); continue; }                                          && ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH * (Data.rrv ? 4:1)) )
822                                            if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, iEdgedWidth/2, pMB->quant, Data.rrv)) {
823                                                    SkipMacroblockP(pMB, sad00);
824                                                    continue;
825                                            }
826                            }
827    
828  /* finally, intra decision */  /* finally, intra decision */
829    
830                          InterBias = MV16_INTER_BIAS;                          InterBias = MV16_INTER_BIAS;
831                          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
832                          if (y != 0)                          if (y != 0)
833                                  if ((pMB - pParam->mb_width)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - pParam->mb_width)->mode == MODE_INTRA ) InterBias -= 80;
834                          if (x != 0)                          if (x != 0)
835                                  if ((pMB - 1)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - 1)->mode == MODE_INTRA ) InterBias -= 80;
836    
837                          if (InterBias < pMB->sad16)  {                          if (Data.chroma) InterBias += 50; // to compensate bigger SAD
838                                  const int32_t deviation =                          if (Data.rrv) InterBias *= 4;
                                         dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,  
                                                   pParam->edged_width);  
839    
840                            if (InterBias < pMB->sad16) {
841                                    int32_t deviation;
842                                    if (!Data.rrv)
843                                            deviation = dev16(pCurrent->y + (x + y * iEdgedWidth) * 16, iEdgedWidth);
844                                    else {
845                                            deviation = dev16(pCurrent->y + (x + y * iEdgedWidth) * 32, iEdgedWidth)
846                                                    + dev16(pCurrent->y + (x + y * iEdgedWidth) * 32 + 16, iEdgedWidth)
847                                                    + dev16(pCurrent->y + (x + y * iEdgedWidth) * 32 + 16 * iEdgedWidth, iEdgedWidth)
848                                                    + dev16(pCurrent->y + (x + y * iEdgedWidth) * 32 + 16 * (iEdgedWidth+1), iEdgedWidth);
849                                    }
850                                  if (deviation < (pMB->sad16 - InterBias)) {                                  if (deviation < (pMB->sad16 - InterBias)) {
851                                          if (++iIntra >= iLimit) return 1;                                          if (++iIntra >= iLimit) return 1;
852                                            SkipMacroblockP(pMB, 0); //same thing
853                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
                                         pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =  
                                                 pMB->mvs[3] = zeroMV;  
                                         pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =  
                                                 pMB->sad8[3] = 0;  
854                                  }                                  }
855                          }                          }
856                  }                  }
857          }          }
858          return 0;  
859            if (current->global_flags & XVID_GMC )  /* first GMC step only for S(GMC)-VOPs */
860            {
861                    current->warp = GlobalMotionEst( pMBs, pParam, current, reference, pRefH, pRefV, pRefHV);
862  }  }
863    
864            return 0;
865    }
866    
 #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  
867    
868  static __inline int  static __inline int
869  make_mask(const VECTOR * const pmv, const int i)  make_mask(const VECTOR * const pmv, const int i)
870  {  {
871          int mask = 0xFF, j;          int mask = 255, j;
872          for (j = 0; j < i; j++) {          for (j = 0; j < i; j++) {
873                  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
874                  if (pmv[i].x == pmv[j].x) {                  if (pmv[i].x == pmv[j].x) {
875                          if (pmv[i].y == pmv[j].y + iDiamondSize) { mask &= ~4; continue; }                          if (pmv[i].y == pmv[j].y + iDiamondSize) mask &= ~4;
876                          if (pmv[i].y == pmv[j].y - iDiamondSize) { mask &= ~8; continue; }                          else if (pmv[i].y == pmv[j].y - iDiamondSize) mask &= ~8;
877                  } else                  } else
878                          if (pmv[i].y == pmv[j].y) {                          if (pmv[i].y == pmv[j].y) {
879                                  if (pmv[i].x == pmv[j].x + iDiamondSize) { mask &= ~1; continue; }                                  if (pmv[i].x == pmv[j].x + iDiamondSize) mask &= ~1;
880                                  if (pmv[i].x == pmv[j].x - iDiamondSize) { mask &= ~2; continue; }                                  else if (pmv[i].x == pmv[j].x - iDiamondSize) mask &= ~2;
881                          }                          }
882          }          }
883          return mask;          return mask;
884  }  }
885    
886  static __inline void  static __inline void
887  PreparePredictionsP(VECTOR * const pmv, int x, int y, const int iWcount,  PreparePredictionsP(VECTOR * const pmv, int x, int y, int iWcount,
888                          const int iHcount, const MACROBLOCK * const prevMB)                          int iHcount, const MACROBLOCK * const prevMB, int rrv)
889  {  {
890    
891  //this function depends on get_pmvdata which means that it sucks. It should get the predictions by itself  //this function depends on get_pmvdata which means that it sucks. It should get the predictions by itself
892            if (rrv) { iWcount /= 2; iHcount /= 2; }
893    
894          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour          if ( (y != 0) && (x < (iWcount-1)) ) {          // [5] top-right neighbour
895                  pmv[5].x = EVEN(pmv[3].x);                  pmv[5].x = EVEN(pmv[3].x);
896                  pmv[5].y = EVEN(pmv[3].y); }                  pmv[5].y = EVEN(pmv[3].y);
897          else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
898    
899          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
900          else pmv[3].x = pmv[3].y = 0;          else pmv[3].x = pmv[3].y = 0;
# Line 642  Line 910 
910          pmv[2].x = EVEN(prevMB->mvs[0].x); // [2] is last frame          pmv[2].x = EVEN(prevMB->mvs[0].x); // [2] is last frame
911          pmv[2].y = EVEN(prevMB->mvs[0].y);          pmv[2].y = EVEN(prevMB->mvs[0].y);
912    
913          if ((x != iWcount-1) && (y != iHcount-1)) {          if ((x < iWcount-1) && (y < iHcount-1)) {
914                  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
915                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y); }                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
916          else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
917    
918            if (rrv) {
919                    int i;
920                    for (i = 0; i < 7; i++) {
921                            pmv[i].x = RRV_MV_SCALEUP(pmv[i].x);
922                            pmv[i].y = RRV_MV_SCALEUP(pmv[i].y);
923                    }
924            }
925  }  }
926    
927  static void  static void
928  SearchP(const uint8_t * const pRef,  SearchP(const IMAGE * const pRef,
929                  const uint8_t * const pRefH,                  const uint8_t * const pRefH,
930                  const uint8_t * const pRefV,                  const uint8_t * const pRefV,
931                  const uint8_t * const pRefHV,                  const uint8_t * const pRefHV,
# Line 658  Line 934 
934                  const int y,                  const int y,
935                  const uint32_t MotionFlags,                  const uint32_t MotionFlags,
936                  const uint32_t iQuant,                  const uint32_t iQuant,
937                  const uint32_t iFcode,                  SearchData * const Data,
938                  const MBParam * const pParam,                  const MBParam * const pParam,
939                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
940                  const MACROBLOCK * const prevMBs,                  const MACROBLOCK * const prevMBs,
# Line 666  Line 942 
942                  MACROBLOCK * const pMB)                  MACROBLOCK * const pMB)
943  {  {
944    
         const int32_t iEdgedWidth = pParam->edged_width;  
   
945          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
946          int32_t temp[5];          VECTOR pmv[7];
         VECTOR currentMV[5], pmv[7];  
         int32_t psad[4], iMinSAD[5];  
         MainSearchFunc * MainSearchPtr;  
         SearchData Data;  
947    
948          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,
949          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,                                                  pParam->width, pParam->height, Data->iFcode - Data->qpel, 0, Data->rrv);
                                 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;  
950    
951          Data.iQuant = iQuant;          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);
         Data.iFcode = iFcode;  
952    
953          if (!(MotionFlags & PMV_HALFPEL16)) {          Data->temp[5] = Data->temp[6] = 0; // chroma-sad cache
954                  Data.min_dx = EVEN(Data.min_dx);          i = Data->rrv ? 2 : 1;
955                  Data.max_dx = EVEN(Data.max_dx);          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16*i;
956                  Data.min_dy = EVEN(Data.min_dy);          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
957                  Data.max_dy = EVEN(Data.max_dy); }          Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
958    
959          for(i = 0;  i < 5; i++) currentMV[i].x = currentMV[i].y = 0;          Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16*i;
960            Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16*i;
961          i = d_mv_bits(pmv[0].x, pmv[0].y, iFcode);          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16*i;
962            Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16*i;
963          iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;          Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
964          iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;          Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
965          iMinSAD[2] = pMB->sad8[1];  
966          iMinSAD[3] = pMB->sad8[2];          Data->lambda16 = lambda_vec16[iQuant];
967          iMinSAD[4] = pMB->sad8[3];          Data->lambda8 = lambda_vec8[iQuant];
968            Data->qpel_precision = 0;
969    
970          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
971    
972          if ((x == 0) && (y == 0)) threshA = 512;          for(i = 0; i < 5; i++)
973          else {                  Data->currentMV[i].x = Data->currentMV[i].y = 0;
974                  threshA = psad[0] + 20;  
975            if (Data->qpel) Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
976            else Data->predMV = pmv[0];
977    
978            i = d_mv_bits(0, 0, Data->predMV, Data->iFcode, 0, 0);
979            Data->iMinSAD[0] = pMB->sad16 + ((Data->lambda16 * i * pMB->sad16)>>10);
980            Data->iMinSAD[1] = pMB->sad8[0] + ((Data->lambda8 * i * (pMB->sad8[0]+NEIGH_8X8_BIAS)) >> 10);
981            Data->iMinSAD[2] = pMB->sad8[1];
982            Data->iMinSAD[3] = pMB->sad8[2];
983            Data->iMinSAD[4] = pMB->sad8[3];
984    
985            if (x | y) {
986                    threshA = Data->temp[0]; // that's when we keep this SAD atm
987                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
988                  if (threshA > 1024) threshA = 1024; }                  else if (threshA > 1024) threshA = 1024;
989            } else threshA = 512;
990    
991          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,
992                                          prevMBs + x + y * pParam->mb_width);                                          prevMBs + x + y * pParam->mb_width, Data->rrv);
993    
994          if (inter4v) CheckCandidate = CheckCandidate16;          if (!Data->rrv) {
995          else CheckCandidate = CheckCandidate16no4v;                  if (inter4v | Data->chroma) CheckCandidate = CheckCandidate16;
996                            else CheckCandidate = CheckCandidate16no4v; //for extra speed
997            } else CheckCandidate = CheckCandidate32;
998    
999  /* main loop. checking all predictions */  /* main loop. checking all predictions (but first, which is 0,0 and has been checked in MotionEstimation())*/
1000    
1001          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
1002                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1003                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  (*CheckCandidate)(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1004                  if (iMinSAD[0] < threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1005          }          }
1006    
1007          if ((iMinSAD[0] <= threshA) ||          if ((Data->iMinSAD[0] <= threshA) ||
1008                          (MVequal(currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
1009                          (iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {                          (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16)))
1010                  inter4v = 0;                  inter4v = 0;
1011                  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;  
                 }  
         }  
1012    
1013          if (MotionFlags & PMV_USESQUARES16)                  MainSearchFunc * MainSearchPtr;
1014                  MainSearchPtr = SquareSearch;                  if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
1015          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
                 MainSearchPtr = AdvDiamondSearch;  
1016                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1017    
1018          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, iDirection);                  (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1019    
1020  /* extended search, diamond starting in 0,0 and in prediction.  /* extended search, diamond starting in 0,0 and in prediction.
1021          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 1023 
1023    
1024          if (MotionFlags & PMV_EXTSEARCH16) {          if (MotionFlags & PMV_EXTSEARCH16) {
1025                  int32_t bSAD;                  int32_t bSAD;
1026                  VECTOR startMV = Data.predMV, backupMV = currentMV[0];                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
1027                            if (Data->rrv) {
1028                                    startMV.x = RRV_MV_SCALEUP(startMV.x);
1029                                    startMV.y = RRV_MV_SCALEUP(startMV.y);
1030                            } else
1031                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?
1032                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);
1033                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1034                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1035    
1036                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1037                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1038                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1039                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1040                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1041                  }                  }
1042    
1043                  backupMV = currentMV[0];                          backupMV = Data->currentMV[0];
1044                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;                          if (MotionFlags & PMV_HALFPELREFINE16 && !Data->rrv) startMV.x = startMV.y = 1;
1045                  else startMV.x = startMV.y = 0;                  else startMV.x = startMV.y = 0;
1046                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1047                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1048    
1049                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1050                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1051                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1052                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1053                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1054                  }                  }
1055          }          }
1056            }
1057    
1058            if (MotionFlags & PMV_HALFPELREFINE16) SubpelRefine(Data);
1059    
1060            for(i = 0; i < 5; i++) {
1061                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1062                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1063            }
1064    
1065            if (Data->qpel && MotionFlags & PMV_QUARTERPELREFINE16) {
1066                    Data->qpel_precision = 1;
1067                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1068                                    pParam->width, pParam->height, Data->iFcode, 1, 0);
1069    
1070                    SubpelRefine(Data);
1071            }
1072    
1073  PMVfast16_Terminate_with_Refine:          if (Data->iMinSAD[0] < (int32_t)iQuant * 30) inter4v = 0;
1074            if (inter4v) {
1075                    SearchData Data8;
1076                    memcpy(&Data8, Data, sizeof(SearchData)); //quick copy of common data
1077    
1078          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);                  Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1079                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1080                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1081                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1082    
1083  PMVfast16_Terminate_without_Refine:                  if (Data->chroma) {
1084                            int sumx = 0, sumy = 0;
1085                            const int div = 1 + Data->qpel;
1086                            const VECTOR * const mv = Data->qpel ? pMB->qmvs : pMB->mvs;
1087    
1088          if (inter4v)                          for (i = 0; i < 4; i++) {
1089                  for(i = 0; i < 4; i++)                                  sumx += mv[i].x / div;
1090                          Search8(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                                  sumy += mv[i].y / div;
1091                            }
1092    
1093                            Data->iMinSAD[1] += ChromaSAD(  (sumx >> 3) + roundtab_76[sumx & 0xf],
1094                                                                                            (sumy >> 3) + roundtab_76[sumy & 0xf], Data);
1095                    }
1096            }
1097    
1098            if (Data->rrv) {
1099                            Data->currentMV[0].x = RRV_MV_SCALEDOWN(Data->currentMV[0].x);
1100                            Data->currentMV[0].y = RRV_MV_SCALEDOWN(Data->currentMV[0].y);
1101            }
1102    
1103          if (!(inter4v) ||          if (!(inter4v) ||
1104                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
1105                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1106  // INTER MODE  // INTER MODE
1107                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1108                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1109                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = Data->iMinSAD[0];
   
                 pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =  
                         pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];  
1110    
1111                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(Data->qpel) {
1112                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->qmvs[0] = pMB->qmvs[1]
1113                                    = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1114                            pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predMV.x;
1115                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predMV.y;
1116                    } else {
1117                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1118                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1119                    }
1120          } else {          } else {
1121  // INTER4V MODE; all other things are already set in Search8  // INTER4V MODE; all other things are already set in Search8
1122                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1123                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1124                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1125          }          }
   
1126  }  }
1127    
1128  static void  static void
# Line 820  Line 1132 
1132                  const MBParam * const pParam,                  const MBParam * const pParam,
1133                  MACROBLOCK * const pMB,                  MACROBLOCK * const pMB,
1134                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
1135                  const int block)                  const int block,
1136                    SearchData * const Data)
1137  {  {
1138          SearchData Data;          int i = 0;
1139            Data->iMinSAD = OldData->iMinSAD + 1 + block;
1140            Data->currentMV = OldData->currentMV + 1 + block;
1141            Data->currentQMV = OldData->currentQMV + 1 + block;
1142    
1143            if(Data->qpel) {
1144                    Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2, y/2, block);
1145                    if (block != 0) i = d_mv_bits(  Data->currentQMV->x, Data->currentQMV->y,
1146                                                                                    Data->predMV, Data->iFcode, 0, 0);
1147            } else {
1148                    Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2, y/2, block);
1149                    if (block != 0) i = d_mv_bits(  Data->currentMV->x, Data->currentMV->y,
1150                                                                                    Data->predMV, Data->iFcode, 0, Data->rrv);
1151            }
1152    
1153          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          *(Data->iMinSAD) += (Data->lambda8 * i * (*Data->iMinSAD + NEIGH_8X8_BIAS))>>10;
         Data.iMinSAD = OldData->iMinSAD + 1 + block;  
         Data.currentMV = OldData->currentMV+1+block;  
         Data.iFcode = OldData->iFcode;  
         Data.iQuant = OldData->iQuant;  
   
         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);  
   
   
         if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {  
   
                 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));  
1154    
1155                  Data.iEdgedWidth = pParam->edged_width;          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8|PMV_QUARTERPELREFINE8)) {
1156                    if (Data->rrv) i = 2; else i = 1;
1157    
1158                  Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Ref = OldData->Ref + i * 8 * ((block&1) + Data->iEdgedWidth*(block>>1));
1159                    Data->RefH = OldData->RefH + i * 8 * ((block&1) + Data->iEdgedWidth*(block>>1));
1160                    Data->RefV = OldData->RefV + i * 8 * ((block&1) + Data->iEdgedWidth*(block>>1));
1161                    Data->RefHV = OldData->RefHV + i * 8 * ((block&1) + Data->iEdgedWidth*(block>>1));
1162    
1163                  get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,                  Data->Cur = OldData->Cur + i * 8 * ((block&1) + Data->iEdgedWidth*(block>>1));
1164                                  pParam->width, pParam->height, OldData->iFcode);                  Data->qpel_precision = 0;
1165    
1166                  CheckCandidate = CheckCandidate8;                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1167                                            pParam->width, pParam->height, Data->iFcode - Data->qpel, 0, Data->rrv);
1168    
1169                    if (!Data->rrv) CheckCandidate = CheckCandidate8;
1170                    else CheckCandidate = CheckCandidate16no4v;
1171    
1172                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & PMV_EXTSEARCH8) {
1173                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1174    
1175                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1176                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1177                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1178                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1179    
1180                          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);     }                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1181    
1182                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                          if(*(Data->iMinSAD) < temp_sad) {
1183                                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1184                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1185                            }
1186          }          }
1187    
1188          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;                  if (MotionFlags & PMV_HALFPELREFINE8) {
1189          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;                          int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1190          pMB->mvs[block] = *(Data.currentMV);  
1191          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                          SubpelRefine(Data); // perform halfpel refine of current best vector
1192    
1193                            if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1194                                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1195                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1196                            }
1197  }  }
1198    
1199  /* B-frames code starts here */                  if (Data->qpel && MotionFlags & PMV_QUARTERPELREFINE8) {
1200                                    Data->qpel_precision = 1;
1201                                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1202                                            pParam->width, pParam->height, Data->iFcode, 1, 0);
1203                                    SubpelRefine(Data);
1204                    }
1205            }
1206    
1207            if (Data->rrv) {
1208                            Data->currentMV->x = RRV_MV_SCALEDOWN(Data->currentMV->x);
1209                            Data->currentMV->y = RRV_MV_SCALEDOWN(Data->currentMV->y);
1210            }
1211    
1212            if(Data->qpel) {
1213                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predMV.x;
1214                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predMV.y;
1215                    pMB->qmvs[block] = *Data->currentQMV;
1216            } else {
1217                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1218                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1219            }
1220    
1221            pMB->mvs[block] = *Data->currentMV;
1222            pMB->sad8[block] = 4 * *Data->iMinSAD;
1223    }
1224    
1225    /* motion estimation for B-frames */
1226    
1227  static __inline VECTOR  static __inline VECTOR
1228  ChoosePred(const MACROBLOCK * const pMB, const uint32_t mode)  ChoosePred(const MACROBLOCK * const pMB, const uint32_t mode)
1229  {  {
1230  /* the stupidiest function ever */  /* the stupidiest function ever */
1231          if (mode == MODE_FORWARD) return pMB->mvs[0];          return (mode == MODE_FORWARD ? pMB->mvs[0] : pMB->b_mvs[0]);
         else return pMB->b_mvs[0];  
1232  }  }
1233    
1234  static void __inline  static void __inline
# Line 896  Line 1246 
1246          pmv[2] = ChoosePred(pMB, mode_curr);          pmv[2] = ChoosePred(pMB, mode_curr);
1247          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);
1248    
         pmv[3].x = pmv[3].y = 0;  
1249          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour
1250                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);
1251                  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);
1252            } else pmv[3].x = pmv[3].y = 0;
1253    
1254          if (y != 0) {          if (y != 0) {
1255                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);
# Line 911  Line 1261 
1261                  pmv[5].x = EVEN(pmv[5].x); pmv[5].y = EVEN(pmv[5].y);                  pmv[5].x = EVEN(pmv[5].x); pmv[5].y = EVEN(pmv[5].y);
1262          } else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
1263    
1264          if ((x != 0)&&(y != 0)) {          if (x != 0 && y != 0) {
1265                  pmv[6] = ChoosePred(pMB-1-iWcount, mode_curr);                  pmv[6] = ChoosePred(pMB-1-iWcount, mode_curr);
1266                  pmv[6].x = EVEN(pmv[5].x); pmv[5].y = EVEN(pmv[5].y);                  pmv[6].x = EVEN(pmv[6].x); pmv[6].y = EVEN(pmv[6].y);
1267          } else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
   
 // more?  
1268  }  }
1269    
1270    
1271  /* search backward or forward, for b-frames */  /* search backward or forward */
1272  static void  static void
1273  SearchBF(       const uint8_t * const pRef,  SearchBF(       const uint8_t * const pRef,
1274                          const uint8_t * const pRefH,                          const uint8_t * const pRefH,
# Line 929  Line 1277 
1277                          const IMAGE * const pCur,                          const IMAGE * const pCur,
1278                          const int x, const int y,                          const int x, const int y,
1279                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
1280                          const uint32_t iFcode,                          const uint32_t iFcode,
1281                          const MBParam * const pParam,                          const MBParam * const pParam,
1282                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
1283                          const VECTOR * const predMV,                          const VECTOR * const predMV,
1284                          int32_t * const best_sad,                          int32_t * const best_sad,
1285                          const int32_t mode_current)                          const int32_t mode_current,
1286                            SearchData * const Data)
1287  {  {
1288    
1289          const int32_t iEdgedWidth = pParam->edged_width;          int i, iDirection = 255, mask;
1290            VECTOR pmv[7];
         int i, iDirection, mask;  
         VECTOR currentMV, pmv[7];  
1291          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1292          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
1293          SearchData Data;          Data->iFcode = iFcode;
1294            Data->qpel_precision = 0;
1295    
1296          Data.iMinSAD = &iMinSAD;          Data->Ref = pRef + (x + y * Data->iEdgedWidth) * 16;
1297          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->RefH = pRefH + (x + y * Data->iEdgedWidth) * 16;
1298          Data.iEdgedWidth = iEdgedWidth;          Data->RefV = pRefV + (x + y * Data->iEdgedWidth) * 16;
1299          Data.currentMV = &currentMV;          Data->RefHV = pRefHV + (x + y * Data->iEdgedWidth) * 16;
1300          Data.iMinSAD = &iMinSAD;  
1301          Data.Ref = pRef + (x + y * iEdgedWidth) * 16;          Data->predMV = *predMV;
         Data.RefH = pRefH + (x + y * iEdgedWidth) * 16;  
         Data.RefV = pRefV + (x + y * iEdgedWidth) * 16;  
         Data.RefHV = pRefHV + (x + y * iEdgedWidth) * 16;  
   
         Data.iQuant = iQuant;  
         Data.iFcode = iFcode;  
         Data.predMV = *predMV;  
   
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,  
                                 pParam->width, pParam->height, iFcode);  
   
         if (!(MotionFlags & PMV_HALFPEL16)) {  
                 Data.min_dx = EVEN(Data.min_dx);  
                 Data.max_dx = EVEN(Data.max_dx);  
                 Data.min_dy = EVEN(Data.min_dy);  
                 Data.max_dy = EVEN(Data.max_dy); } // no-halpel and b-frames. do we need it?  
   
   
         pmv[0] = Data.predMV;  
         PreparePredictionsBF(pmv, x, y, pParam->mb_width,  
                                         pMB, mode_current);  
1302    
1303          currentMV.x = currentMV.y = 0;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1304                                    pParam->width, pParam->height, iFcode - Data->qpel, 0, 0);
1305    
1306            pmv[0] = Data->predMV;
1307            if (Data->qpel) { pmv[0].x /= 2; pmv[0].y /= 2; }
1308    
1309            PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
1310    
1311            Data->currentMV->x = Data->currentMV->y = 0;
1312          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1313    
1314  // main loop. checking all predictions  // main loop. checking all predictions
1315          for (i = 0; i < 8; i++) {          for (i = 0; i < 7; i++) {
1316                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1317                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1318          }          }
1319    
1320          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
1321                  MainSearchPtr = SquareSearch;          else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
         else if (MotionFlags & PMV_ADVANCEDDIAMOND16)  
                 MainSearchPtr = AdvDiamondSearch;  
1322                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1323    
1324          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1325    
1326            SubpelRefine(Data);
1327    
1328          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (Data->qpel && *Data->iMinSAD < *best_sad + 300) {
1329                    Data->currentQMV->x = 2*Data->currentMV->x;
1330                    Data->currentQMV->y = 2*Data->currentMV->y;
1331                    Data->qpel_precision = 1;
1332                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1333                                            pParam->width, pParam->height, iFcode, 1, 0);
1334                    SubpelRefine(Data);
1335            }
1336    
1337  // three bits are needed to code backward mode. four for forward  // three bits are needed to code backward mode. four for forward
 // we treat the bits just like they were vector's  
         if (mode_current == MODE_FORWARD) iMinSAD +=  4 * lambda_vec16[iQuant];  
         else iMinSAD +=  3 * lambda_vec16[iQuant];  
1338    
1339            if (mode_current == MODE_FORWARD) *Data->iMinSAD += 4 * Data->lambda16;
1340            else *Data->iMinSAD += 3 * Data->lambda16;
1341    
1342          if (iMinSAD < *best_sad) {          if (*Data->iMinSAD < *best_sad) {
1343                  *best_sad = iMinSAD;                  *best_sad = *Data->iMinSAD;
1344                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1345                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  if (Data->qpel) {
1346                  pMB->pmvs[0].y = currentMV.y - predMV->y;                          pMB->pmvs[0].x = Data->currentQMV->x - predMV->x;
1347                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                          pMB->pmvs[0].y = Data->currentQMV->y - predMV->y;
1348                  else pMB->b_mvs[0] = currentMV;                          if (mode_current == MODE_FORWARD)
1349                                    pMB->qmvs[0] = *Data->currentQMV;
1350                            else
1351                                    pMB->b_qmvs[0] = *Data->currentQMV;
1352                    } else {
1353                            pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1354                            pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1355                    }
1356                    if (mode_current == MODE_FORWARD) pMB->mvs[0] = *Data->currentMV;
1357                    else pMB->b_mvs[0] = *Data->currentMV;
1358          }          }
1359    
1360            if (mode_current == MODE_FORWARD) *(Data->currentMV+2) = *Data->currentMV;
1361            else *(Data->currentMV+1) = *Data->currentMV; //we store currmv for interpolate search
1362  }  }
1363    
1364  static int32_t  static void
1365  SearchDirect(const uint8_t * const f_Ref,  SkipDecisionB(const IMAGE * const pCur,
1366                                    const IMAGE * const f_Ref,
1367                                    const IMAGE * const b_Ref,
1368                                    MACROBLOCK * const pMB,
1369                                    const uint32_t x, const uint32_t y,
1370                                    const SearchData * const Data)
1371    {
1372            int dx = 0, dy = 0, b_dx = 0, b_dy = 0;
1373            int32_t sum;
1374            const int div = 1 + Data->qpel;
1375            int k;
1376            const uint32_t stride = Data->iEdgedWidth/2;
1377    //this is not full chroma compensation, only it's fullpel approximation. should work though
1378    
1379            for (k = 0; k < 4; k++) {
1380                    dy += Data->directmvF[k].y / div;
1381                    dx += Data->directmvF[0].x / div;
1382                    b_dy += Data->directmvB[0].y / div;
1383                    b_dx += Data->directmvB[0].x / div;
1384            }
1385    
1386            dy = (dy >> 3) + roundtab_76[dy & 0xf];
1387            dx = (dx >> 3) + roundtab_76[dx & 0xf];
1388            b_dy = (b_dy >> 3) + roundtab_76[b_dy & 0xf];
1389            b_dx = (b_dx >> 3) + roundtab_76[b_dx & 0xf];
1390    
1391            sum = sad8bi(pCur->u + 8 * x + 8 * y * stride,
1392                                            f_Ref->u + (y*8 + dy/2) * stride + x*8 + dx/2,
1393                                            b_Ref->u + (y*8 + b_dy/2) * stride + x*8 + b_dx/2,
1394                                            stride);
1395    
1396            if (sum >= 2 * MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) return; //no skip
1397    
1398            sum += sad8bi(pCur->v + 8*x + 8 * y * stride,
1399                                            f_Ref->v + (y*8 + dy/2) * stride + x*8 + dx/2,
1400                                            b_Ref->v + (y*8 + b_dy/2) * stride + x*8 + b_dx/2,
1401                                            stride);
1402    
1403            if (sum < 2 * MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) pMB->mode = MODE_DIRECT_NONE_MV; //skipped
1404    }
1405    
1406    static __inline uint32_t
1407    SearchDirect(const IMAGE * const f_Ref,
1408                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1409                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
1410                                  const uint8_t * const f_RefHV,                                  const uint8_t * const f_RefHV,
1411                                  const uint8_t * const b_Ref,                                  const IMAGE * const b_Ref,
1412                                  const uint8_t * const b_RefH,                                  const uint8_t * const b_RefH,
1413                                  const uint8_t * const b_RefV,                                  const uint8_t * const b_RefV,
1414                                  const uint8_t * const b_RefHV,                                  const uint8_t * const b_RefHV,
1415                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1416                                  const int x, const int y,                                  const int x, const int y,
1417                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1418                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1419                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1420                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1421                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1422                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1423                                    SearchData * const Data)
1424    
1425  {  {
1426          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
1427          int32_t iMinSAD = 0, skip_sad;          int k = (x + Data->iEdgedWidth*y) * 16;
         int k;  
         VECTOR currentMV;  
1428          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
         SearchData Data;  
1429    
1430          Data.iMinSAD = &iMinSAD;          *Data->iMinSAD = 256*4096;
1431          Data.Cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;          Data->Ref = f_Ref->y + k;
1432          Data.iEdgedWidth = iEdgedWidth;          Data->RefH = f_RefH + k;
1433          Data.currentMV = &currentMV;          Data->RefV = f_RefV + k;
1434          Data.iQuant = iQuant;          Data->RefHV = f_RefHV + k;
1435          Data.referencemv = b_mb->mvs;          Data->bRef = b_Ref->y + k;
1436            Data->bRefH = b_RefH + k;
1437          Data.Ref= f_Ref + (x + iEdgedWidth*y) * 16;          Data->bRefV = b_RefV + k;
1438          Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;          Data->bRefHV = b_RefHV + k;
1439          Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;  
1440          Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;          k = Data->qpel ? 4 : 2;
1441          Data.bRef = b_Ref + (x + iEdgedWidth*y) * 16;          Data->max_dx = k * (pParam->width - x * 16);
1442          Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;          Data->max_dy = k * (pParam->height - y * 16);
1443          Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;          Data->min_dx = -k * (16 + x * 16);
1444          Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;          Data->min_dy = -k * (16 + y * 16);
1445  /*  
1446  //What we do here is a complicated version of CheckCandidateDirect(0,0);          Data->referencemv = Data->qpel ? b_mb->qmvs : b_mb->mvs;
1447  get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16, pParam->width, pParam->height, 19);          Data->qpel_precision = 0;
   
 */  
         Data.max_dx = 2 * pParam->width - 2 * (x) * 16;  
         Data.max_dy = 2 * pParam->height - 2 * (y) * 16;  
         Data.min_dx = -(2 * 16 + 2 * (x) * 16);  
         Data.min_dy = -(2 * 16 + 2 * (y) * 16);  
1448    
1449          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1450                  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);
1451                  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;
1452                  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);
1453                  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;
1454    
1455          if (( pMB->mvs[k].x > Data.max_dx ) || ( pMB->mvs[k].x < Data.min_dx )                  if ( (pMB->b_mvs[k].x > Data->max_dx) | (pMB->b_mvs[k].x < Data->min_dx)
1456                          || ( pMB->mvs[k].y > Data.max_dy ) || ( pMB->mvs[k].y < Data.min_dy )                          | (pMB->b_mvs[k].y > Data->max_dy) | (pMB->b_mvs[k].y < Data->min_dy) ) {
1457                          || ( 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);  
 */  
1458                  *best_sad = 256*4096; // in that case, we won't use direct mode                  *best_sad = 256*4096; // in that case, we won't use direct mode
1459                  pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"                  pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
1460                  pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;  /* because backwards and interpol might rely on this */                          pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;
1461                  return 0; }                          return 256*4096;
1462                    }
1463                    if (b_mb->mode != MODE_INTER4V) {
1464                            pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1465                            pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];
1466                            Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1467                            Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1468                            break;
1469                    }
1470            }
1471    
1472            CheckCandidate = b_mb->mode == MODE_INTER4V ? CheckCandidateDirect : CheckCandidateDirectno4v;
1473    
1474          if (b_mb->mode != MODE_INTER4V) {          (*CheckCandidate)(0, 0, 255, &k, Data);
1475                  iMinSAD = sad16bi(Data.Cur,  
1476                                                  get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,  // initial (fast) skip decision
1477                                                                  x, y, 16, &pMB->mvs[0], iEdgedWidth),          if (*Data->iMinSAD < pMB->quant * INITIAL_SKIP_THRESH * 2) {
1478                                                  get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,                  //possible skip - checking chroma
1479                                                                  x, y, 16, &pMB->b_mvs[0], iEdgedWidth), iEdgedWidth);                  SkipDecisionB(pCur, f_Ref, b_Ref, pMB, x, y, Data);
1480                    if (pMB->mode == MODE_DIRECT_NONE_MV) return *Data->iMinSAD; // skip.
1481                  Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];          }
1482                  Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];  
1483                  break;          skip_sad = *Data->iMinSAD;
         }  
         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);  
         }  
   
 // skip decision  
         if (iMinSAD < (int32_t)iQuant * SKIP_THRESH_B) {  
                 pMB->mode = MODE_DIRECT_NONE_MV;  
                 return iMinSAD; }  
   
         skip_sad = 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;  
1484    
1485  //  DIRECT MODE DELTA VECTOR SEARCH.  //  DIRECT MODE DELTA VECTOR SEARCH.
1486  //      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 1489 
1489                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1490                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1491    
1492          (*MainSearchPtr)(0, 0, &Data, 255);          (*MainSearchPtr)(0, 0, Data, 255);
1493    
1494          HalfpelRefine(&Data);          SubpelRefine(Data);
1495    
1496          iMinSAD +=  1 * lambda_vec16[iQuant]; // one bit is needed to code direct mode. we treat this bit just like it was vector's          *best_sad = *Data->iMinSAD;
         *best_sad = iMinSAD;  
1497    
1498          if (b_mb->mode == MODE_INTER4V)          if (Data->qpel || b_mb->mode == MODE_INTER4V) pMB->mode = MODE_DIRECT;
                 pMB->mode = MODE_DIRECT;  
1499          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1500    
1501          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1502    
1503          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1504                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1505                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = (     (Data->currentMV->x == 0)
1506                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1507                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          :pMB->mvs[k].x - Data->referencemv[k].x);
1508                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1509                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1510                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1511                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1512                    if (Data->qpel) {
1513                            pMB->qmvs[k].x = pMB->mvs[k].x; pMB->mvs[k].x /= 2;
1514                            pMB->b_qmvs[k].x = pMB->b_mvs[k].x; pMB->b_mvs[k].x /= 2;
1515                            pMB->qmvs[k].y = pMB->mvs[k].y; pMB->mvs[k].y /= 2;
1516                            pMB->b_qmvs[k].y = pMB->b_mvs[k].y; pMB->b_mvs[k].y /= 2;
1517                    }
1518    
1519                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1520                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1521                          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];
1522                            pMB->qmvs[3] = pMB->qmvs[2] = pMB->qmvs[1] = pMB->qmvs[0];
1523                            pMB->b_qmvs[3] = pMB->b_qmvs[2] = pMB->b_qmvs[1] = pMB->b_qmvs[0];
1524                          break;                          break;
1525                  }                  }
1526          }          }
1527          return 0;//skip_sad;          return skip_sad;
1528  }  }
1529    
1530  static __inline void  static void
1531  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const uint8_t * const f_Ref,
1532                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1533                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
# Line 1168  Line 1541 
1541                                  const uint32_t fcode,                                  const uint32_t fcode,
1542                                  const uint32_t bcode,                                  const uint32_t bcode,
1543                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1544                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1545                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1546                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1547                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1548                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1549                                    SearchData * const fData)
1550    
1551  {  {
 /* 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". */  
   
         const int32_t iEdgedWidth = pParam->edged_width;  
1552    
1553          int iDirection, i, j;          int iDirection, i, j;
1554          int32_t iMinSAD = 256*4096;          SearchData bData;
         VECTOR currentMV[3];  
         SearchData fData, bData;  
   
   
         fData.iMinSAD = bData.iMinSAD = &iMinSAD;  
   
         fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
         fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;  
         fData.currentMV = currentMV; bData.currentMV = currentMV + 1;  
         fData.iQuant = bData.iQuant = iQuant;  
         fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;  
   
   
         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;  
1555    
1556            fData->qpel_precision = 0;
1557            memcpy(&bData, fData, sizeof(SearchData)); //quick copy of common data
1558            *fData->iMinSAD = 4096*256;
1559            bData.currentMV++; bData.currentQMV++;
1560            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1561    
1562            i = (x + y * fData->iEdgedWidth) * 16;
1563            bData.bRef = fData->Ref = f_Ref + i;
1564            bData.bRefH = fData->RefH = f_RefH + i;
1565            bData.bRefV = fData->RefV = f_RefV + i;
1566            bData.bRefHV = fData->RefHV = f_RefHV + i;
1567            bData.Ref = fData->bRef = b_Ref + i;
1568            bData.RefH = fData->bRefH = b_RefH + i;
1569            bData.RefV = fData->bRefV = b_RefV + i;
1570            bData.RefHV = fData->bRefHV = b_RefHV + i;
1571    
1572            bData.bpredMV = fData->predMV = *f_predMV;
1573            fData->bpredMV = bData.predMV = *b_predMV;
1574            fData->currentMV[0] = fData->currentMV[2];
1575    
1576            get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode - fData->qpel, 0, 0);
1577            get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode - fData->qpel, 0, 0);
1578    
1579            if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1580            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dx;
1581            if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dy;
1582            if (fData->currentMV[0].y < fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1583    
1584            if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1585            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dx;
1586            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dy;
1587            if (fData->currentMV[1].y < bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1588    
1589          currentMV[0] = pMB->mvs[0];          CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
         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);  
   
 //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  
1590    
1591    //diamond
1592          do {          do {
1593                  iDirection = 255;                  iDirection = 255;
1594                  // forward MV moves                  // forward MV moves
1595                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
1596    
1597                  CheckCandidateInt(i + 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1598                  CheckCandidateInt(i, j + 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1599                  CheckCandidateInt(i - 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1600                  CheckCandidateInt(i, j - 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
1601    
1602                  // backward MV moves                  // backward MV moves
1603                  i = currentMV[1].x; j = currentMV[1].y;                  i = fData->currentMV[1].x; j = fData->currentMV[1].y;
1604                  currentMV[2] = currentMV[0];                  fData->currentMV[2] = fData->currentMV[0];
1605                    CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1606                  CheckCandidateInt(i + 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1607                  CheckCandidateInt(i, j + 2, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
1608                  CheckCandidateInt(i - 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, &bData);
                 CheckCandidateInt(i, j - 2, 0, &iDirection, &bData);  
1609    
1610          } while (!(iDirection));          } while (!(iDirection));
1611    
1612  /* halfpel refinement. luckly we can use normal halfpel function for it */  //qpel refinement
1613            if (fData->qpel) {
1614          if (MotionFlags & PMV_HALFPELREFINE16) {                  if (*fData->iMinSAD > *best_sad + 500) return;
1615                  CheckCandidate = CheckCandidateInt;                  CheckCandidate = CheckCandidateInt;
1616                  HalfpelRefine(&fData);                  fData->qpel_precision = bData.qpel_precision = 1;
1617                  currentMV[2] = currentMV[0];                  get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, 1, 0);
1618                  HalfpelRefine(&bData);                  get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, 1, 0);
1619          }                  fData->currentQMV[2].x = fData->currentQMV[0].x = 2 * fData->currentMV[0].x;
1620                    fData->currentQMV[2].y = fData->currentQMV[0].y = 2 * fData->currentMV[0].y;
1621  // 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;
1622          iMinSAD +=  2 * lambda_vec16[iQuant];                  fData->currentQMV[1].y = 2 * fData->currentMV[1].y;
1623          if (iMinSAD < *best_sad) {                  SubpelRefine(fData);
1624                  *best_sad = iMinSAD;                  if (*fData->iMinSAD > *best_sad + 300) return;
1625                  pMB->mvs[0] = currentMV[0];                  fData->currentQMV[2] = fData->currentQMV[0];
1626                  pMB->b_mvs[0] = currentMV[1];                  SubpelRefine(&bData);
1627            }
1628    
1629            *fData->iMinSAD += (2+3) * fData->lambda16; // two bits are needed to code interpolate mode.
1630    
1631            if (*fData->iMinSAD < *best_sad) {
1632                    *best_sad = *fData->iMinSAD;
1633                    pMB->mvs[0] = fData->currentMV[0];
1634                    pMB->b_mvs[0] = fData->currentMV[1];
1635                  pMB->mode = MODE_INTERPOLATE;                  pMB->mode = MODE_INTERPOLATE;
1636                    if (fData->qpel) {
1637                            pMB->qmvs[0] = fData->currentQMV[0];
1638                            pMB->b_qmvs[0] = fData->currentQMV[1];
1639                            pMB->pmvs[1].x = pMB->qmvs[0].x - f_predMV->x;
1640                            pMB->pmvs[1].y = pMB->qmvs[0].y - f_predMV->y;
1641                            pMB->pmvs[0].x = pMB->b_qmvs[0].x - b_predMV->x;
1642                            pMB->pmvs[0].y = pMB->b_qmvs[0].y - b_predMV->y;
1643                    } else {
1644                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;
1645                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;
1646                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;
1647                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;
1648          }          }
1649  }  }
1650    }
1651    
1652  void  void
1653  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
# Line 1277  Line 1661 
1661                                           const IMAGE * const f_refV,                                           const IMAGE * const f_refV,
1662                                           const IMAGE * const f_refHV,                                           const IMAGE * const f_refHV,
1663                                           // backward (future) reference                                           // backward (future) reference
1664                                           const MACROBLOCK * const b_mbs,                                           const FRAMEINFO * const b_reference,
1665                                           const IMAGE * const b_ref,                                           const IMAGE * const b_ref,
1666                                           const IMAGE * const b_refH,                                           const IMAGE * const b_refH,
1667                                           const IMAGE * const b_refV,                                           const IMAGE * const b_refV,
1668                                           const IMAGE * const b_refHV)                                           const IMAGE * const b_refHV)
1669  {  {
1670          uint32_t i, j;          uint32_t i, j;
1671          int32_t best_sad, skip_sad;          int32_t best_sad;
1672            uint32_t skip_sad;
1673          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;
1674          static const VECTOR zeroMV={0,0};          const MACROBLOCK * const b_mbs = b_reference->mbs;
1675    
1676          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
1677    
1678          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1679          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
1680    
1681          // note: i==horizontal, j==vertical  // some pre-inintialized data for the rest of the search
1682    
1683            SearchData Data;
1684            int32_t iMinSAD;
1685            VECTOR currentMV[3];
1686            VECTOR currentQMV[3];
1687            memset(&Data, 0, sizeof(SearchData));
1688            Data.iEdgedWidth = pParam->edged_width;
1689            Data.currentMV = currentMV; Data.currentQMV = currentQMV;
1690            Data.iMinSAD = &iMinSAD;
1691            Data.lambda16 = lambda_vec16[frame->quant];
1692            Data.chroma = frame->quant;
1693            Data.qpel = pParam->m_quarterpel;
1694            Data.rounding = 0;
1695    
1696            Data.RefQ = f_refV->u; // a good place, also used in MC (for similar purpose)
1697            // note: i==horizontal, j==vertical
1698          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
1699    
1700                  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 1703 
1703                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;
1704                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;
1705    
1706  /* 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 */
1707                            if (b_reference->coding_type != S_VOP)
1708                          if (b_mb->mode == MODE_NOT_CODED) {                          if (b_mb->mode == MODE_NOT_CODED) {
1709                                  pMB->mode = MODE_NOT_CODED;                                  pMB->mode = MODE_NOT_CODED;
1710                                  continue;                                  continue;
1711                          }                          }
1712    
1713                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
1714                            pMB->quant = frame->quant;
1715    
1716  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
1717          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
1718                            skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
1719                          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,  
1720                                                                          &frame->image,                                                                          &frame->image,
1721                                                                          i, j,                                                                          i, j,
1722                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
1723                                                                          TRB, TRD,                                                                          TRB, TRD,
1724                                                                          pParam,                                                                          pParam,
1725                                                                          pMB, b_mb,                                                                          pMB, b_mb,
1726                                                                          &best_sad);                                                                          &best_sad,
1727                                                                            &Data);
1728    
                         if (!(frame->global_flags & XVID_HALFPEL)) best_sad = skip_sad = 256*4096;  
                         else  
1729                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1730    
 //                      best_sad = 256*4096; //uncomment to disable Directsearch.  
 //      To disable any other mode, just comment the function call  
   
1731                          // forward search                          // forward search
1732                          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,
1733                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1734                                                  frame->motion_flags,                                                  frame->motion_flags,
1735                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
1736                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
1737                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
1738    
1739                          // backward search                          // backward search
1740                          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,
1741                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1742                                                  frame->motion_flags,                                                  frame->motion_flags,
1743                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
1744                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
1745                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
1746    
1747                          // 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
   
1748                          SearchInterpolate(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                          SearchInterpolate(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
1749                                                  b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                                                  b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
1750                                                  &frame->image,                                                  &frame->image,
1751                                                  i, j,                                                  i, j,
1752                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
1753                                                  frame->motion_flags,                                                  frame->motion_flags,
1754                                                  frame->quant, pParam,                                                  pParam,
1755                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
1756                                                  pMB, &best_sad);                                                  pMB, &best_sad,
1757                                                    &Data);
1758    
1759    // final skip decision
1760                            if ( (skip_sad < frame->quant * MAX_SAD00_FOR_SKIP*2)
1761                                            && ((100*best_sad)/(skip_sad+1) > FINAL_SKIP_THRESH) )
1762                                    SkipDecisionB(&frame->image, f_ref, b_ref, pMB, i, j, &Data);
1763    
1764                          switch (pMB->mode) {                          switch (pMB->mode) {
1765                                  case MODE_FORWARD:                                  case MODE_FORWARD:
1766                                          f_count++;                                          f_count++;
1767                                          f_predMV = pMB->mvs[0];                                          f_predMV = Data.qpel ? pMB->qmvs[0] : pMB->mvs[0];
1768                                          break;                                          break;
1769                                  case MODE_BACKWARD:                                  case MODE_BACKWARD:
1770                                          b_count++;                                          b_count++;
1771                                          b_predMV = pMB->b_mvs[0];                                          b_predMV = Data.qpel ? pMB->b_qmvs[0] : pMB->b_mvs[0];
1772                                          break;                                          break;
1773                                  case MODE_INTERPOLATE:                                  case MODE_INTERPOLATE:
1774                                          i_count++;                                          i_count++;
1775                                          f_predMV = pMB->mvs[0];                                          f_predMV = Data.qpel ? pMB->qmvs[0] : pMB->mvs[0];
1776                                          b_predMV = pMB->b_mvs[0];                                          b_predMV = Data.qpel ? pMB->b_qmvs[0] : pMB->b_mvs[0];
1777                                          break;                                          break;
1778                                  case MODE_DIRECT:                                  case MODE_DIRECT:
1779                                  case MODE_DIRECT_NO4V:                                  case MODE_DIRECT_NO4V:
1780                                          d_count++;                                          d_count++;
                                         break;  
1781                                  default:                                  default:
1782                                          break;                                          break;
1783                          }                          }
1784                  }                  }
1785          }          }
   
 //      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);  
   
1786  }  }
1787    
 /* Hinted ME starts here */  
   
1788  static __inline void  static __inline void
1789  Search8hinted(  const SearchData * const OldData,  MEanalyzeMB (   const uint8_t * const pRef,
1790                                  const int x, const int y,                                  const uint8_t * const pCur,
1791                                  const uint32_t MotionFlags,                                  const int x,
1792                                    const int y,
1793                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1794                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMBs,
1795                                  const MACROBLOCK * const pMBs,                                  SearchData * const Data)
                                 const int block)  
1796  {  {
         SearchData Data;  
         MainSearchFunc *MainSearchPtr;  
1797    
1798          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          int i, mask;
1799          Data.iMinSAD = OldData->iMinSAD + 1 + block;          VECTOR pmv[3];
1800          Data.currentMV = OldData->currentMV+1+block;          MACROBLOCK * pMB = &pMBs[x + y * pParam->mb_width];
         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));  
1801    
1802          CheckCandidate = CheckCandidate8;          for (i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
1803    
1804          if (block != 0)          //median is only used as prediction. it doesn't have to be real
1805                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *          if (x == 1 && y == 1) Data->predMV.x = Data->predMV.y = 0;
1806                                                                  d_mv_bits(      Data.currentMV->x - Data.predMV.x,          else
1807                                                                                          Data.currentMV->y - Data.predMV.y,                  if (x == 1) //left macroblock does not have any vector now
1808                                                                                          Data.iFcode);                          Data->predMV = (pMB - pParam->mb_width)->mvs[0]; // top instead of median
1809                    else if (y == 1) // top macroblock doesn't have it's vector
1810                            Data->predMV = (pMB - 1)->mvs[0]; // left instead of median
1811                            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); //else median
1812    
1813            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1814                                    pParam->width, pParam->height, Data->iFcode - pParam->m_quarterpel, 0, Data->rrv);
1815    
1816          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,          Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
1817                                  pParam->width, pParam->height, OldData->iFcode);          Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
1818    
1819          if (pMB->mode == MODE_INTER4V) {          pmv[1].x = EVEN(pMB->mvs[0].x);
1820                  int dummy;          pmv[1].y = EVEN(pMB->mvs[0].y);
1821                  CheckCandidate8(pMB->mvs[block].x, pMB->mvs[block].y, 0, &dummy, &Data); }          pmv[2].x = EVEN(Data->predMV.x);
1822            pmv[2].y = EVEN(Data->predMV.y);
1823            pmv[0].x = pmv[0].y = 0;
1824    
1825          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;          CheckCandidate32I(0, 0, 255, &i, Data);
1826                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;  
1827                          else MainSearchPtr = DiamondSearch;          if (*Data->iMinSAD > 4 * MAX_SAD00_FOR_SKIP * 4) {
1828    
1829          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);                  if (!(mask = make_mask(pmv, 1)))
1830                            CheckCandidate32I(pmv[1].x, pmv[1].y, mask, &i, Data);
1831                    if (!(mask = make_mask(pmv, 2)))
1832                            CheckCandidate32I(pmv[2].x, pmv[2].y, mask, &i, Data);
1833    
1834          if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                  if (*Data->iMinSAD > 4 * MAX_SAD00_FOR_SKIP * 4) // diamond only if needed
1835                            DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
1836    
1837          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;                  for (i = 0; i < 4; i++) {
1838          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;                          MACROBLOCK * MB = &pMBs[x + (i&1) + (y+(i>>1)) * pParam->mb_width];
1839          pMB->mvs[block] = *(Data.currentMV);                          MB->mvs[0] = MB->mvs[1] = MB->mvs[2] = MB->mvs[3] = Data->currentMV[i];
1840          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                          MB->mode = MODE_INTER;
1841                            MB->sad16 = Data->iMinSAD[i+1];
1842                    }
1843            }
1844  }  }
1845    
1846    #define INTRA_BIAS              2500
1847    #define INTRA_THRESH    1500
1848    #define INTER_THRESH    1400
1849    
1850  static void  int
1851  SearchPhinted ( const uint8_t * const pRef,  MEanalysis(     const IMAGE * const pRef,
1852                                  const uint8_t * const pRefH,                          FRAMEINFO * const Current,
1853                                  const uint8_t * const pRefV,                          MBParam * const pParam,
1854                                  const uint8_t * const pRefHV,                          int maxIntra, //maximum number if non-I frames
1855                                  const IMAGE * const pCur,                          int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame
1856                                  const int x,                          int bCount) // number of B frames in a row
                                 const int y,  
                                 const uint32_t MotionFlags,  
                                 const uint32_t iQuant,  
                                 const uint32_t iFcode,  
                                 const MBParam * const pParam,  
                                 const MACROBLOCK * const pMBs,  
                                 int inter4v,  
                                 MACROBLOCK * const pMB)  
1857  {  {
1858            uint32_t x, y, intra = 0;
1859            int sSAD = 0;
1860            MACROBLOCK * const pMBs = Current->mbs;
1861            const IMAGE * const pCurrent = &Current->image;
1862            int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH;
1863    
1864          const int32_t iEdgedWidth = pParam->edged_width;          int32_t iMinSAD[5], temp[5];
   
         int i;  
1865          VECTOR currentMV[5];          VECTOR currentMV[5];
         int32_t iMinSAD[5];  
         int32_t temp[5];  
         MainSearchFunc * MainSearchPtr;  
1866          SearchData Data;          SearchData Data;
1867            Data.iEdgedWidth = pParam->edged_width;
         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,  
                                 pParam->width, pParam->height, iFcode);  
   
         Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
         Data.iEdgedWidth = iEdgedWidth;  
1868          Data.currentMV = currentMV;          Data.currentMV = currentMV;
1869          Data.iMinSAD = iMinSAD;          Data.iMinSAD = iMinSAD;
1870          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data.iFcode = Current->fcode;
1871          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data.rrv = Current->global_flags & XVID_REDUCED;
         Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;  
         Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;  
1872          Data.temp = temp;          Data.temp = temp;
1873          Data.iQuant = iQuant;          CheckCandidate = CheckCandidate32I;
1874          Data.iFcode = iFcode;  
1875            if (intraCount != 0 && intraCount < 10) // we're right after an I frame
1876                    IntraThresh += 4 * (intraCount - 10) * (intraCount - 10);
1877            else
1878                    if ( 5*(maxIntra - intraCount) < maxIntra) // we're close to maximum. 2 sec when max is 10 sec
1879                            IntraThresh -= (IntraThresh * (maxIntra - 5*(maxIntra - intraCount)))/maxIntra;
1880    
1881            InterThresh += 400 * (1 - bCount);
1882            if (InterThresh < 300) InterThresh = 300;
1883    
1884            if (sadInit) (*sadInit) ();
1885    
1886            for (y = 1; y < pParam->mb_height-1; y += 2) {
1887                    for (x = 1; x < pParam->mb_width-1; x += 2) {
1888                            int i;
1889    
1890                            if (bCount == 0) pMBs[x + y * pParam->mb_width].mvs[0] = zeroMV;
1891    
1892                            MEanalyzeMB(pRef->y, pCurrent->y, x, y, pParam, pMBs, &Data);
1893    
1894          if (!(MotionFlags & PMV_HALFPEL16)) {                          for (i = 0; i < 4; i++) {
1895                  Data.min_dx = EVEN(Data.min_dx);                                  int dev;
1896                  Data.max_dx = EVEN(Data.max_dx);                                  MACROBLOCK *pMB = &pMBs[x+(i&1) + (y+(i>>1)) * pParam->mb_width];
1897                  Data.min_dy = EVEN(Data.min_dy);                                  if (pMB->sad16 > IntraThresh) {
1898                  Data.max_dy = EVEN(Data.max_dy);                                          dev = dev16(pCurrent->y + (x + (i&1) + (y + (i>>1)) * pParam->edged_width) * 16,
1899                                                                            pParam->edged_width);
1900                                            if (dev + IntraThresh < pMB->sad16) {
1901                                                    pMB->mode = MODE_INTRA;
1902                                                    if (++intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return I_VOP;
1903                                            }
1904                                    }
1905                                    sSAD += pMB->sad16;
1906          }          }
1907                    }
1908            }
1909            sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
1910            if (sSAD > IntraThresh + INTRA_BIAS) return I_VOP;
1911            if (sSAD > InterThresh ) return P_VOP;
1912            emms();
1913            return B_VOP;
1914    
1915          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;  }
1916    
         if (pMB->dquant != NO_CHANGE) inter4v = 0;  
1917    
1918          if (inter4v)  static WARPPOINTS
1919                  CheckCandidate = CheckCandidate16;  GlobalMotionEst(const MACROBLOCK * const pMBs,
1920          else CheckCandidate = CheckCandidate16no4v;                                  const MBParam * const pParam,
1921                                    const FRAMEINFO * const current,
1922                                    const FRAMEINFO * const reference,
1923                                    const IMAGE * const pRefH,
1924                                    const IMAGE * const pRefV,
1925                                    const IMAGE * const pRefHV      )
1926    {
1927    
1928            const int deltax=8;             // upper bound for difference between a MV and it's neighbour MVs
1929            const int deltay=8;
1930            const int grad=512;             // lower bound for deviation in MB
1931    
1932          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);          WARPPOINTS gmc;
         pMB->mvs[0].y = EVEN(pMB->mvs[0].y);  
         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.min_dx) pMB->mvs[0].x = Data.min_dx;  
         if (pMB->mvs[0].y > Data.max_dy) pMB->mvs[0].y = Data.max_dy;  
         if (pMB->mvs[0].y < Data.min_dy) pMB->mvs[0].y = Data.min_dy;  
   
         CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);  
   
         if (pMB->mode == MODE_INTER4V)  
                 for (i = 1; i < 4; i++) { // all four vectors will be used as four predictions for 16x16 search  
                         pMB->mvs[i].x = EVEN(pMB->mvs[i].x);  
                         pMB->mvs[i].y = EVEN(pMB->mvs[i].y);  
                         if (!(make_mask(pMB->mvs, i)))  
                                 CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);  
                 }  
   
         if (MotionFlags & PMV_USESQUARES16)  
                 MainSearchPtr = SquareSearch;  
         else if (MotionFlags & PMV_ADVANCEDDIAMOND16)  
                 MainSearchPtr = AdvDiamondSearch;  
                 else MainSearchPtr = DiamondSearch;  
1933    
1934          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          uint32_t mx, my;
1935    
1936          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          int MBh = pParam->mb_height;
1937            int MBw = pParam->mb_width;
1938    
1939          if (inter4v)          int *MBmask= calloc(MBh*MBw,sizeof(int));
1940                  for(i = 0; i < 4; i++)          double DtimesF[4] = { 0.,0., 0., 0. };
1941                          Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);          double sol[4] = { 0., 0., 0., 0. };
1942            double a,b,c,n,denom;
1943            double meanx,meany;
1944            int num,oldnum;
1945    
1946          if (!(inter4v) ||          if (!MBmask) { fprintf(stderr,"Mem error\n"); return gmc;}
                 (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {  
 // INTER MODE  
1947    
1948                  pMB->mode = MODE_INTER;  // filter mask of all blocks
                 pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]  
                         = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];  
1949    
1950                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =          for (my = 1; my < MBh-1; my++)
1951                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];          for (mx = 1; mx < MBw-1; mx++)
1952            {
1953                    const int mbnum = mx + my * MBw;
1954                    const MACROBLOCK *pMB = &pMBs[mbnum];
1955                    const VECTOR mv = pMB->mvs[0];
1956    
1957                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
1958                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          continue;
         } else {  
 // INTER4V MODE; all other things are already set in Search8hinted  
                 pMB->mode = MODE_INTER4V;  
                 pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;  
         }  
1959    
1960                    if ( ( (ABS(mv.x -   (pMB-1)->mvs[0].x) < deltax) && (ABS(mv.y -   (pMB-1)->mvs[0].y) < deltay) )
1961                    &&   ( (ABS(mv.x -   (pMB+1)->mvs[0].x) < deltax) && (ABS(mv.y -   (pMB+1)->mvs[0].y) < deltay) )
1962                    &&   ( (ABS(mv.x - (pMB-MBw)->mvs[0].x) < deltax) && (ABS(mv.y - (pMB-MBw)->mvs[0].y) < deltay) )
1963                    &&   ( (ABS(mv.x - (pMB+MBw)->mvs[0].x) < deltax) && (ABS(mv.y - (pMB+MBw)->mvs[0].y) < deltay) ) )
1964                            MBmask[mbnum]=1;
1965  }  }
1966    
1967  void          for (my = 1; my < MBh-1; my++)
1968  MotionEstimationHinted( MBParam * const pParam,          for (mx = 1; mx < MBw-1; mx++)
                                                 FRAMEINFO * const current,  
                                                 FRAMEINFO * const reference,  
                                                 const IMAGE * const pRefH,  
                                                 const IMAGE * const pRefV,  
                                                 const IMAGE * const pRefHV)  
1969  {  {
1970          MACROBLOCK *const pMBs = current->mbs;                  const uint8_t *const pCur = current->image.y + 16*my*pParam->edged_width + 16*mx;
         const IMAGE *const pCurrent = &current->image;  
         const IMAGE *const pRef = &reference->image;  
1971    
1972          uint32_t x, y;                  const int mbnum = mx + my * MBw;
1973                    if (!MBmask[mbnum])
1974                            continue;
1975    
1976          if (sadInit) (*sadInit) ();                  if (sad16 ( pCur, pCur+1 , pParam->edged_width, 65536) <= grad )
1977                            MBmask[mbnum] = 0;
1978                    if (sad16 ( pCur, pCur+pParam->edged_width, pParam->edged_width, 65536) <= grad )
1979                            MBmask[mbnum] = 0;
1980    
1981          for (y = 0; y < pParam->mb_height; y++) {          }
                 for (x = 0; x < pParam->mb_width; x++)  {  
                         int32_t sad00;  
1982    
1983                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];          emms();
1984    
1985  //intra mode is copied from the first pass. At least for the time being          do {            /* until convergence */
                         if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;  
1986    
1987                          if (!(current->global_flags & XVID_LUMIMASKING)) {          a = b = c = n = 0;
1988                                  pMB->dquant = NO_CHANGE;          DtimesF[0] = DtimesF[1] = DtimesF[2] = DtimesF[3] = 0.;
1989                                  pMB->quant = current->quant; }          for (my = 0; my < MBh; my++)
1990                    for (mx = 0; mx < MBw; mx++)
1991                    {
1992                            const int mbnum = mx + my * MBw;
1993                            const MACROBLOCK *pMB = &pMBs[mbnum];
1994                            const VECTOR mv = pMB->mvs[0];
1995    
1996                          if (pMB->dquant == NO_CHANGE) //no skip otherwise, anyway                          if (!MBmask[mbnum])
1997                                  sad00 = pMB->sad16                                  continue;
                                         = sad16(pCurrent->y + (x + y * pParam->edged_width) * 16,  
                                                                 pRef->y + (x + y * pParam->edged_width) * 16,  
                                                                 pParam->edged_width, 256*4096 );  
                         else sad00 = 256*4096;  
1998    
1999                            n++;
2000                            a += 16*mx+8;
2001                            b += 16*my+8;
2002                            c += (16*mx+8)*(16*mx+8)+(16*my+8)*(16*my+8);
2003    
2004                            DtimesF[0] += (double)mv.x;
2005                            DtimesF[1] += (double)mv.x*(16*mx+8) + (double)mv.y*(16*my+8);
2006                            DtimesF[2] += (double)mv.x*(16*my+8) - (double)mv.y*(16*mx+8);
2007                            DtimesF[3] += (double)mv.y;
2008                    }
2009    
2010            denom = a*a+b*b-c*n;
2011    
2012    /* Solve the system:     sol = (D'*E*D)^{-1} D'*E*F   */
2013    /* D'*E*F has been calculated in the same loop as matrix */
2014    
2015            sol[0] = -c*DtimesF[0] + a*DtimesF[1] + b*DtimesF[2];
2016            sol[1] =  a*DtimesF[0] - n*DtimesF[1]                + b*DtimesF[3];
2017            sol[2] =  b*DtimesF[0]                - n*DtimesF[2] - a*DtimesF[3];
2018            sol[3] =                 b*DtimesF[1] - a*DtimesF[2] - c*DtimesF[3];
2019    
2020            sol[0] /= denom;
2021            sol[1] /= denom;
2022            sol[2] /= denom;
2023            sol[3] /= denom;
2024    
2025            meanx = meany = 0.;
2026            oldnum = 0;
2027            for (my = 0; my < MBh; my++)
2028                    for (mx = 0; mx < MBw; mx++)
2029                    {
2030                            const int mbnum = mx + my * MBw;
2031                            const MACROBLOCK *pMB = &pMBs[mbnum];
2032                            const VECTOR mv = pMB->mvs[0];
2033    
2034  //initial skip decision                          if (!MBmask[mbnum])
2035                                    continue;
2036    
2037                          if ( (pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)                          oldnum++;
2038                                  && ( //(pMB->mode == MODE_NOT_CODED) ||                          meanx += ABS(( sol[0] + (16*mx+8)*sol[1] + (16*my+8)*sol[2] ) - mv.x );
2039                                          (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant) )) ) {                          meany += ABS(( sol[3] + (16*my+8)*sol[1] - (16*mx+8)*sol[2] ) - mv.y );
                                 if (sad00 < pMB->quant * INITIAL_SKIP_THRESH) {  
                                         SkipMacroblockP(pMB, sad00);  
                                         continue; } //skipped  
                         }  
                         else sad00 = 256*4096;  
2040    
2041                          if (pMB->mode == MODE_NOT_CODED)                  }
                                 SearchP(        pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,  
                                                         y, current->motion_flags, pMB->quant,  
                                                         current->fcode, pParam, pMBs, reference->mbs,  
                                                         current->global_flags & XVID_INTER4V, pMB);  
2042    
2043            if (2*meanx > oldnum)   /* mittlere Abweichung von Ebene */
2044                    meanx /= oldnum;
2045                          else                          else
2046                                  SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                  meanx = 0.5;
2047                                                          y, current->motion_flags, pMB->quant,          if (2*meany > oldnum)
2048                                                          current->fcode, pParam, pMBs,                  meany /= oldnum;
2049                                                          current->global_flags & XVID_INTER4V, pMB);          else
2050                    meanx = 0.5;
2051    
2052  /* final skip decision, a.k.a. "the vector you found, really that good?" */  //      fprintf(stderr,"meanx = %8.5f  meany = %8.5f   %d\n",meanx,meany, oldnum);
                         if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)  
                                 if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)  
                                 SkipMacroblockP(pMB, sad00);  
2053    
2054            num = 0;
2055            for (my = 0; my < MBh; my++)
2056                    for (mx = 0; mx < MBw; mx++)
2057                    {
2058                            const int mbnum = mx + my * MBw;
2059                            const MACROBLOCK *pMB = &pMBs[mbnum];
2060                            const VECTOR mv = pMB->mvs[0];
2061    
2062                            if (!MBmask[mbnum])
2063                                    continue;
2064    
2065                            if  ( ( ABS(( sol[0] + (16*mx+8)*sol[1] + (16*my+8)*sol[2] ) - mv.x ) > meanx )
2066                               || ( ABS(( sol[3] + (16*my+8)*sol[1] - (16*mx+8)*sol[2] ) - mv.y ) > meany ) )
2067                                    MBmask[mbnum]=0;
2068                            else
2069                                    num++;
2070                  }                  }
2071    
2072            } while ( (oldnum != num) && (num>=4) );
2073    
2074            if (num < 4)
2075            {
2076                    gmc.duv[0].x= gmc.duv[0].y= gmc.duv[1].x= gmc.duv[1].y= gmc.duv[2].x= gmc.duv[2].y=0;
2077            } else {
2078    
2079                    gmc.duv[0].x=(int)(sol[0]+0.5);
2080                    gmc.duv[0].y=(int)(sol[3]+0.5);
2081    
2082                    gmc.duv[1].x=(int)(sol[1]*pParam->width+0.5);
2083                    gmc.duv[1].y=(int)(-sol[2]*pParam->width+0.5);
2084    
2085                    gmc.duv[2].x=0;
2086                    gmc.duv[2].y=0;
2087          }          }
2088  }  //      fprintf(stderr,"wp1 = ( %4d, %4d)  wp2 = ( %4d, %4d) \n", gmc.duv[0].x, gmc.duv[0].y, gmc.duv[1].x, gmc.duv[1].y);
2089    
2090            free(MBmask);
2091    
2092            return gmc;
2093    }

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

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