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

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

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