[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 539, Wed Sep 25 21:28:48 2002 UTC revision 754, Wed Jan 1 13:04:06 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"
# Line 46  Line 48 
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 (22)  #define MAX_CHROMA_SAD_FOR_SKIP (22)
 #define SKIP_THRESH_B (25)  
51    
52  #define CHECK_CANDIDATE(X,Y,D) { \  #define CHECK_CANDIDATE(X,Y,D) { \
53  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }
54    
 #define iDiamondSize 2  
   
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    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 */  /* 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;
         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 117  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 125  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                  data->currentMV[0].x = x; data->currentMV[0].y = y;                  current->x = x; current->y = y;
347                  *dir = Direction; }                  *dir = Direction; }
348  }  }
349    
350  static void  static void
351  CheckCandidate16no4vI(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidate32I(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
352  {  {
353          int32_t sad;  // maximum speed - for P/B/I decision
354    
355          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
356                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
357    
358          sad = lambda_vec16[data->iQuant] *          data->temp[0] = sad32v_c(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),
359                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);                                                          data->iEdgedWidth, data->temp+1);
360            if (data->temp[0] < *(data->iMinSAD)) {
361          sad += sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),                  *(data->iMinSAD) = data->temp[0];
                                         data->iEdgedWidth, 256*4096);  
   
         if (sad < *(data->iMinSAD)) {  
                 *(data->iMinSAD) = sad;  
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 234  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 268  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 288  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 313  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 348  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 366  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 421  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 471  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 485  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)
# Line 530  Line 725 
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 = 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 = 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 548  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          // some pre-initialized thingies for SearchP          // some pre-initialized thingies for SearchP
758          int32_t temp[5];          int32_t temp[8];
759          VECTOR currentMV[5];          VECTOR currentMV[5];
760            VECTOR currentQMV[5];
761          int32_t iMinSAD[5];          int32_t iMinSAD[5];
762          SearchData Data;          SearchData Data;
763            memset(&Data, 0, sizeof(SearchData));
764          Data.iEdgedWidth = pParam->edged_width;          Data.iEdgedWidth = pParam->edged_width;
765          Data.currentMV = currentMV;          Data.currentMV = currentMV;
766            Data.currentQMV = currentQMV;
767          Data.iMinSAD = iMinSAD;          Data.iMinSAD = iMinSAD;
768          Data.temp = temp;          Data.temp = temp;
769          Data.iFcode = current->fcode;          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            Data.RefQ = pRefV->u; // a good place, also used in MC (for similar purpose)
782          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
783    
784          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < mb_height; y++) {
785                  for (x = 0; x < pParam->mb_width; x++)  {                  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                                                  &Data, 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)) {
# Line 617  Line 874 
874                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
875                                          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 648  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;
# Line 666  Line 932 
932      else pmv[4].x = pmv[4].y = 0;      else pmv[4].x = pmv[4].y = 0;
933    
934          // [1] median prediction          // [1] median prediction
935          pmv[1].x = EVEN(pmv[0].x); pmv[1].y = EVEN(pmv[0].y);          if (rrv) { //median is in halfzero-precision
936                    pmv[1].x = RRV_MV_SCALEUP(pmv[0].x);
937                    pmv[1].y = RRV_MV_SCALEUP(pmv[0].y);
938            } else { pmv[1].x = EVEN(pmv[0].x); pmv[1].y = EVEN(pmv[0].y); }
939    
940          pmv[0].x = pmv[0].y = 0; // [0] is zero; not used in the loop (checked before) but needed here for make_mask          pmv[0].x = pmv[0].y = 0; // [0] is zero; not used in the loop (checked before) but needed here for make_mask
941    
942          pmv[2].x = EVEN(prevMB->mvs[0].x); // [2] is last frame          pmv[2].x = EVEN(prevMB->mvs[0].x); // [2] is last frame
943          pmv[2].y = EVEN(prevMB->mvs[0].y);          pmv[2].y = EVEN(prevMB->mvs[0].y);
944    
945          if ((x != iWcount-1) && (y != iHcount-1)) {          if ((x < iWcount-1) && (y < iHcount-1)) {
946                  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
947                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
948          } else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
949    
950            if (rrv) {
951                    int i;
952                    for (i = 0; i < 7; i++) {
953                            pmv[i].x = RRV_MV_SCALEDOWN(pmv[i].x);
954                            pmv[i].x = RRV_MV_SCALEUP(pmv[i].x); // a trick
955                    }
956            }
957  }  }
958    
959  static void  static void
960  SearchP(const uint8_t * const pRef,  SearchP(const IMAGE * const pRef,
961                  const uint8_t * const pRefH,                  const uint8_t * const pRefH,
962                  const uint8_t * const pRefV,                  const uint8_t * const pRefV,
963                  const uint8_t * const pRefHV,                  const uint8_t * const pRefHV,
# Line 700  Line 977 
977          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
978          VECTOR pmv[7];          VECTOR pmv[7];
979    
         get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()  
980          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
981                                  pParam->width, pParam->height, Data->iFcode);                                                  pParam->width, pParam->height, Data->iFcode - Data->qpel, 0, Data->rrv);
   
         Data->predMV = pmv[0];  
         Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;  
         Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;  
         Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;  
         Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;  
         Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;  
982    
983          Data->iQuant = iQuant;          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()
   
         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); }  
984    
985          for(i = 0;  i < 5; i++) Data->iMinSAD[i] = 256*4096;          Data->temp[5] = Data->temp[7] = 256*4096; // to reset chroma-sad cache
986            if (Data->rrv) i = 2; else i = 1;
987            Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16*i;
988            Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
989            Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
990    
991            Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16*i;
992            Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16*i;
993            Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16*i;
994            Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16*i;
995            Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
996            Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
997    
998            Data->lambda16 = lambda_vec16[iQuant];
999            Data->lambda8 = lambda_vec8[iQuant];
1000            Data->qpel_precision = 0;
1001    
1002          if (inter4v) CheckCandidate = CheckCandidate16;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
         else CheckCandidate = CheckCandidate16no4v;  
1003    
1004          (*CheckCandidate)(Data->predMV.x, Data->predMV.y, 0, &iDirection, Data);          for(i = 0;  i < 5; i++)
1005                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
1006    
1007          for(i = 0;  i < 5; i++) Data->currentMV[i].x = Data->currentMV[i].y = 0;          if (pParam->m_quarterpel) Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1008            else Data->predMV = pmv[0];
1009    
1010          i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);          i = d_mv_bits(0, 0, Data->predMV, Data->iFcode, 0, 0);
1011          Data->iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;          Data->iMinSAD[0] = pMB->sad16 + (Data->lambda16 * i * pMB->sad16)/1000;
1012          Data->iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;          Data->iMinSAD[1] = pMB->sad8[0] + (Data->lambda8 * i * (pMB->sad8[0]+NEIGH_8X8_BIAS))/100;
1013          Data->iMinSAD[2] = pMB->sad8[1];          Data->iMinSAD[2] = pMB->sad8[1];
1014          Data->iMinSAD[3] = pMB->sad8[2];          Data->iMinSAD[3] = pMB->sad8[2];
1015          Data->iMinSAD[4] = pMB->sad8[3];          Data->iMinSAD[4] = pMB->sad8[3];
1016    
         if (pMB->dquant != NO_CHANGE) inter4v = 0;  
   
1017          if ((x == 0) && (y == 0)) threshA = 512;          if ((x == 0) && (y == 0)) threshA = 512;
1018          else {          else {
1019                  threshA = Data->temp[0] + 20;                  threshA = Data->temp[0]; // that's when we keep this SAD atm
1020                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
1021                  if (threshA > 1024) threshA = 1024; }                  if (threshA > 1024) threshA = 1024; }
1022    
1023          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,
1024                                          prevMBs + x + y * pParam->mb_width);                                          prevMBs + x + y * pParam->mb_width, Data->rrv);
1025    
1026            if (Data->rrv) CheckCandidate = CheckCandidate32;
1027            else if (inter4v || Data->chroma) CheckCandidate = CheckCandidate16;
1028                    else CheckCandidate = CheckCandidate16no4v; //for extra speed
1029    
1030  /* main loop. checking all predictions */  /* main loop. checking all predictions */
1031    
1032          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
1033                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1034                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, Data);                  (*CheckCandidate)(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1035                  if (Data->iMinSAD[0] <= threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1036          }          }
1037    
# Line 774  Line 1055 
1055                  if (MotionFlags & PMV_EXTSEARCH16) {                  if (MotionFlags & PMV_EXTSEARCH16) {
1056                          int32_t bSAD;                          int32_t bSAD;
1057                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
1058                            if (Data->rrv) {
1059                                    startMV.x = RRV_MV_SCALEUP(startMV.x);
1060                                    startMV.y = RRV_MV_SCALEUP(startMV.y);
1061                            } else
1062                          if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?                          if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?
1063                                  startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);                                  startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);
1064                          if (!(MVequal(startMV, backupMV))) {                          if (!(MVequal(startMV, backupMV))) {
1065                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1066    
1067                                  CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1068                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1069                                  if (bSAD < Data->iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1070                                          Data->currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
# Line 787  Line 1072 
1072                          }                          }
1073    
1074                          backupMV = Data->currentMV[0];                          backupMV = Data->currentMV[0];
1075                          if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;                          if (!MotionFlags & PMV_HALFPELREFINE16 || Data->rrv) startMV.x = startMV.y = 0;
1076                          else startMV.x = startMV.y = 0;                          else startMV.x = startMV.y = 1;
1077                          if (!(MVequal(startMV, backupMV))) {                          if (!(MVequal(startMV, backupMV))) {
1078                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1079    
1080                                  CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1081                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1082                                  if (bSAD < Data->iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1083                                          Data->currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
# Line 801  Line 1086 
1086                  }                  }
1087          }          }
1088    
1089          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);          if (MotionFlags & PMV_HALFPELREFINE16) SubpelRefine(Data);
1090    
1091            for(i = 0; i < 5; i++) {
1092                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1093                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1094            }
1095    
1096            if((Data->qpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1097    
1098                    Data->qpel_precision = 1;
1099                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1100                                    pParam->width, pParam->height, Data->iFcode, 1, 0);
1101    
1102                    SubpelRefine(Data);
1103            }
1104    
1105            if (Data->iMinSAD[0] < (int32_t)iQuant * 30 ) inter4v = 0;
1106          if (inter4v) {          if (inter4v) {
1107                  SearchData Data8;                  SearchData Data8;
1108                  Data8.iFcode = Data->iFcode;                  Data8.iFcode = Data->iFcode;
1109                  Data8.iQuant = Data->iQuant;                  Data8.lambda8 = Data->lambda8;
1110                  Data8.iEdgedWidth = Data->iEdgedWidth;                  Data8.iEdgedWidth = Data->iEdgedWidth;
1111                    Data8.RefQ = Data->RefQ;
1112                    Data8.qpel = Data->qpel;
1113                    Data8.rrv = Data->rrv;
1114                  Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);                  Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1115                  Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);                  Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1116                  Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);                  Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1117                  Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);                  Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1118    
1119                    if (Data->chroma) {
1120                            int sumx, sumy;
1121    
1122                            if(pParam->m_quarterpel) {
1123                                    sumx = pMB->qmvs[0].x/2 + pMB->qmvs[1].x/2 + pMB->qmvs[2].x/2 + pMB->qmvs[3].x/2;
1124                                    sumy = pMB->qmvs[0].y/2 + pMB->qmvs[1].y/2 + pMB->qmvs[2].y/2 + pMB->qmvs[3].y/2;
1125                            } else {
1126                                    sumx = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1127                                    sumy = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1128                            }
1129    
1130                            Data->iMinSAD[1] += ChromaSAD(  (sumx >> 3) + roundtab_76[sumx & 0xf],
1131                                                                                            (sumy >> 3) + roundtab_76[sumy & 0xf], Data);
1132                    }
1133            }
1134    
1135            if (Data->rrv) {
1136                            Data->currentMV[0].x = RRV_MV_SCALEDOWN(Data->currentMV[0].x);
1137                            Data->currentMV[0].y = RRV_MV_SCALEDOWN(Data->currentMV[0].y);
1138          }          }
1139    
1140          if (!(inter4v) ||          if (!(inter4v) ||
# Line 825  Line 1148 
1148                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1149                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1150    
1151                    if(pParam->m_quarterpel) {
1152                            pMB->qmvs[0] = pMB->qmvs[1]
1153                                    = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1154                            pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predMV.x;
1155                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predMV.y;
1156                    } else {
1157                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1158                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1159                    }
1160          } else {          } else {
1161  // INTER4V MODE; all other things are already set in Search8  // INTER4V MODE; all other things are already set in Search8
1162                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1163                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1164                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1165          }          }
   
1166  }  }
1167    
1168  static void  static void
# Line 846  Line 1175 
1175                  const int block,                  const int block,
1176                  SearchData * const Data)                  SearchData * const Data)
1177  {  {
1178          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          int i = 0;
1179          Data->iMinSAD = OldData->iMinSAD + 1 + block;          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1180          Data->currentMV = OldData->currentMV + 1 + block;          Data->currentMV = OldData->currentMV + 1 + block;
1181            Data->currentQMV = OldData->currentQMV + 1 + block;
1182    
1183            if(pParam->m_quarterpel) {
1184                    Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2, y/2, block);
1185                    if (block != 0) i = d_mv_bits(  Data->currentQMV->x, Data->currentQMV->y,
1186                                                                                    Data->predMV, Data->iFcode, 0, 0);
1187    
1188            } else {
1189                    Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2, y/2, block);
1190                    if (block != 0) {
1191                            if (block != 0) i = d_mv_bits(  Data->currentMV->x, Data->currentMV->y,
1192                                                                                            Data->predMV, Data->iFcode, 0, Data->rrv);
1193                    }
1194            }
1195    
1196          if (block != 0)          *(Data->iMinSAD) += (Data->lambda8 * i * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
                 *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *  
                                                                 d_mv_bits(      Data->currentMV->x - Data->predMV.x,  
                                                                                         Data->currentMV->y - Data->predMV.y,  
                                                                                         Data->iFcode);  
1197    
1198          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
1199                    if (Data->rrv) i = 2; else i = 1;
1200    
1201                  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));
1202                  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));
1203                  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));
1204                  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));
1205    
1206                  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));
1207                    Data->qpel_precision = 0;
1208    
1209                  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,
1210                                  pParam->width, pParam->height, OldData->iFcode);                                          pParam->width, pParam->height, OldData->iFcode - Data->qpel, 0, Data->rrv);
1211    
1212                  CheckCandidate = CheckCandidate8;                  if (Data->rrv) CheckCandidate = CheckCandidate16no4v;
1213                    else CheckCandidate = CheckCandidate8;
1214    
1215                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & PMV_EXTSEARCH8) {
1216                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1217    
1218                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1219                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1220                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1221                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1222    
1223                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);    }                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1224    
1225                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(Data);                          if(*(Data->iMinSAD) < temp_sad) {
1226                                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1227                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1228                            }
1229                    }
1230    
1231                    if (MotionFlags & PMV_HALFPELREFINE8) {
1232                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1233    
1234                            SubpelRefine(Data); // perform halfpel refine of current best vector
1235    
1236                            if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1237                                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1238                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1239                            }
1240          }          }
1241    
1242                    if(Data->qpel) {
1243                            if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1244                                    (MotionFlags & PMV_QUARTERPELREFINE8)) {
1245                            Data->qpel_precision = 1;
1246                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1247                                    pParam->width, pParam->height, OldData->iFcode, 1, 0);
1248                            SubpelRefine(Data);
1249                            }
1250                    }
1251            }
1252    
1253            if (Data->rrv) {
1254                            Data->currentMV->x = RRV_MV_SCALEDOWN(Data->currentMV->x);
1255                            Data->currentMV->y = RRV_MV_SCALEDOWN(Data->currentMV->y);
1256            }
1257    
1258            if(Data->qpel) {
1259                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predMV.x;
1260                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predMV.y;
1261                    pMB->qmvs[block] = *(Data->currentQMV);
1262            } else {
1263          pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;          pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1264          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1265            }
1266    
1267          pMB->mvs[block] = *(Data->currentMV);          pMB->mvs[block] = *(Data->currentMV);
1268          pMB->sad8[block] =  4 * (*Data->iMinSAD);          pMB->sad8[block] =  4 * (*Data->iMinSAD);
   
1269  }  }
1270    
1271  /* B-frames code starts here */  /* B-frames code starts here */
# Line 947  Line 1326 
1326                          const IMAGE * const pCur,                          const IMAGE * const pCur,
1327                          const int x, const int y,                          const int x, const int y,
1328                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
1329                          const uint32_t iFcode,                          const uint32_t iFcode,
1330                          const MBParam * const pParam,                          const MBParam * const pParam,
1331                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
1332                          const VECTOR * const predMV,                          const VECTOR * const predMV,
1333                          int32_t * const best_sad,                          int32_t * const best_sad,
1334                          const int32_t mode_current)                          const int32_t mode_current,
1335                            SearchData * const Data)
1336  {  {
1337    
1338          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1339    
1340          int i, iDirection, mask;          int i, iDirection = 255, mask;
1341          VECTOR currentMV, pmv[7];          VECTOR pmv[7];
1342          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1343          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
1344          SearchData Data;          Data->iFcode = iFcode;
1345            Data->qpel_precision = 0;
1346    
1347            Data->Ref = pRef + (x + y * iEdgedWidth) * 16;
1348            Data->RefH = pRefH + (x + y * iEdgedWidth) * 16;
1349            Data->RefV = pRefV + (x + y * iEdgedWidth) * 16;
1350            Data->RefHV = pRefHV + (x + y * iEdgedWidth) * 16;
1351    
1352          Data.iMinSAD = &iMinSAD;          Data->predMV = *predMV;
1353          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
1354          Data.iEdgedWidth = iEdgedWidth;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1355          Data.currentMV = &currentMV;                                  pParam->width, pParam->height, iFcode - Data->qpel, 0, 0);
         Data.iMinSAD = &iMinSAD;  
         Data.Ref = pRef + (x + y * iEdgedWidth) * 16;  
         Data.RefH = pRefH + (x + y * iEdgedWidth) * 16;  
         Data.RefV = pRefV + (x + y * iEdgedWidth) * 16;  
         Data.RefHV = pRefHV + (x + y * iEdgedWidth) * 16;  
   
         Data.iQuant = iQuant;  
         Data.iFcode = iFcode;  
         Data.predMV = *predMV;  
   
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,  
                                 pParam->width, pParam->height, iFcode);  
   
         if (!(MotionFlags & PMV_HALFPEL16)) {  
                 Data.min_dx = EVEN(Data.min_dx);  
                 Data.max_dx = EVEN(Data.max_dx);  
                 Data.min_dy = EVEN(Data.min_dy);  
                 Data.max_dy = EVEN(Data.max_dy); } // no-halpel and b-frames. do we need it?  
   
   
         pmv[0] = Data.predMV;  
         PreparePredictionsBF(pmv, x, y, pParam->mb_width,  
                                         pMB, mode_current);  
1356    
1357          currentMV.x = currentMV.y = 0;          pmv[0] = Data->predMV;
1358            if (Data->qpel) { pmv[0].x /= 2; pmv[0].y /= 2; }
1359            PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
1360    
1361            Data->currentMV->x = Data->currentMV->y = 0;
1362          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1363    
1364  // main loop. checking all predictions  // main loop. checking all predictions
1365          for (i = 0; i < 8; i++) {          for (i = 0; i < 7; i++) {
1366                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1367                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1368          }          }
1369    
1370          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1008  Line 1373 
1373                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1374                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1375    
1376          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1377    
1378          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          SubpelRefine(Data);
1379    
1380            if (Data->qpel && *Data->iMinSAD < *best_sad + 300) {
1381                    Data->currentQMV->x = 2*Data->currentMV->x;
1382                    Data->currentQMV->y = 2*Data->currentMV->y;
1383                    Data->qpel_precision = 1;
1384                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1385                                            pParam->width, pParam->height, iFcode, 1, 0);
1386                    SubpelRefine(Data);
1387            }
1388    
1389  // 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];  
1390    
1391            if (mode_current == MODE_FORWARD) *Data->iMinSAD +=  4 * Data->lambda16;
1392            else *Data->iMinSAD +=  3 * Data->lambda16;
1393    
1394          if (iMinSAD < *best_sad) {          if (*Data->iMinSAD < *best_sad) {
1395                  *best_sad = iMinSAD;                  *best_sad = *Data->iMinSAD;
1396                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1397                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  if (Data->qpel) {
1398                  pMB->pmvs[0].y = currentMV.y - predMV->y;                          pMB->pmvs[0].x = Data->currentQMV->x - predMV->x;
1399                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                          pMB->pmvs[0].y = Data->currentQMV->y - predMV->y;
1400                  else pMB->b_mvs[0] = currentMV;                          if (mode_current == MODE_FORWARD)
1401                                    pMB->qmvs[0] = *Data->currentQMV;
1402                            else
1403                                    pMB->b_qmvs[0] = *Data->currentQMV;
1404                    } else {
1405                            pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1406                            pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1407                    }
1408                    if (mode_current == MODE_FORWARD) pMB->mvs[0] = *Data->currentMV;
1409                    else pMB->b_mvs[0] = *Data->currentMV;
1410          }          }
1411            if (mode_current == MODE_FORWARD)  *(Data->currentMV+2) = *Data->currentMV;
1412            else *(Data->currentMV+1) = *Data->currentMV; //we store currmv for interpolate search
1413    
1414  }  }
1415    
1416  static int32_t  static void
1417    SkipDecisionB(const IMAGE * const pCur,
1418                              const IMAGE * const f_Ref,
1419                              const IMAGE * const b_Ref,
1420                              MACROBLOCK * const pMB,
1421                              const uint32_t quant,
1422                              const uint32_t x, const uint32_t y,
1423                              const SearchData * const Data)
1424    {
1425            int dx, dy, b_dx, b_dy;
1426            uint32_t sum;
1427    //this is not full chroma compensation, only it's fullpel approximation. should work though
1428            if (Data->qpel) {
1429                    dy = Data->directmvF[0].y/2 + Data->directmvF[1].y/2 +
1430                                    Data->directmvF[2].y/2 + Data->directmvF[3].y/2;
1431    
1432                    dx = Data->directmvF[0].x/2 + Data->directmvF[1].x/2 +
1433                                    Data->directmvF[2].x/2 + Data->directmvF[3].x/2;
1434    
1435                    b_dy = Data->directmvB[0].y/2 + Data->directmvB[1].y/2 +
1436                                    Data->directmvB[2].y/2 + Data->directmvB[3].y/2;
1437    
1438                    b_dx = Data->directmvB[0].x/2 + Data->directmvB[1].x/2 +
1439                                    Data->directmvB[2].x/2 + Data->directmvB[3].x/2;
1440    
1441            } else {
1442                    dy = Data->directmvF[0].y + Data->directmvF[1].y +
1443                                    Data->directmvF[2].y + Data->directmvF[3].y;
1444    
1445                    dx = Data->directmvF[0].x + Data->directmvF[1].x +
1446                                    Data->directmvF[2].x + Data->directmvF[3].x;
1447    
1448                    b_dy = Data->directmvB[0].y + Data->directmvB[1].y +
1449                                    Data->directmvB[2].y + Data->directmvB[3].y;
1450    
1451                    b_dx = Data->directmvB[0].x + Data->directmvB[1].x +
1452                                    Data->directmvB[2].x + Data->directmvB[3].x;
1453            }
1454    
1455    
1456            dy = (dy >> 3) + roundtab_76[dy & 0xf];
1457            dx = (dx >> 3) + roundtab_76[dx & 0xf];
1458            b_dy = (b_dy >> 3) + roundtab_76[b_dy & 0xf];
1459            b_dx = (b_dx >> 3) + roundtab_76[b_dx & 0xf];
1460    
1461            sum = sad8bi(pCur->u + 8*x + 8*y*(Data->iEdgedWidth/2),
1462                                            f_Ref->u + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1463                                            b_Ref->u + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1464                                            Data->iEdgedWidth/2);
1465            sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1466                                            f_Ref->v + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1467                                            b_Ref->v + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1468                                            Data->iEdgedWidth/2);
1469    
1470            if (sum < 2*MAX_CHROMA_SAD_FOR_SKIP * quant) pMB->mode = MODE_DIRECT_NONE_MV; //skipped
1471    }
1472    
1473    
1474    
1475    static __inline uint32_t
1476  SearchDirect(const IMAGE * const f_Ref,  SearchDirect(const IMAGE * const f_Ref,
1477                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1478                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
# Line 1041  Line 1484 
1484                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1485                                  const int x, const int y,                                  const int x, const int y,
1486                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1487                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1488                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1489                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1490                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1491                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1492                                    SearchData * const Data)
1493    
1494  {  {
1495          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
         int32_t iMinSAD = 266*4096, skip_sad;  
1496          int k;          int k;
1497          VECTOR currentMV;  
1498          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
         SearchData Data;  
1499    
1500          Data.iMinSAD = &iMinSAD;          *Data->iMinSAD = 256*4096;
1501          Data.Cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;  
1502          Data.iEdgedWidth = iEdgedWidth;          Data->Ref = f_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1503          Data.currentMV = &currentMV;          Data->RefH = f_RefH + (x + Data->iEdgedWidth*y) * 16;
1504          Data.iQuant = iQuant;          Data->RefV = f_RefV + (x + Data->iEdgedWidth*y) * 16;
1505          Data.referencemv = b_mb->mvs;          Data->RefHV = f_RefHV + (x + Data->iEdgedWidth*y) * 16;
1506            Data->bRef = b_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1507          Data.Ref= f_Ref->y + (x + iEdgedWidth*y) * 16;          Data->bRefH = b_RefH + (x + Data->iEdgedWidth*y) * 16;
1508          Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;          Data->bRefV = b_RefV + (x + Data->iEdgedWidth*y) * 16;
1509          Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;          Data->bRefHV = b_RefHV + (x + Data->iEdgedWidth*y) * 16;
1510          Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;  
1511          Data.bRef = b_Ref->y + (x + iEdgedWidth*y) * 16;          Data->max_dx = 2 * pParam->width - 2 * (x) * 16;
1512          Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;          Data->max_dy = 2 * pParam->height - 2 * (y) * 16;
1513          Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;          Data->min_dx = -(2 * 16 + 2 * (x) * 16);
1514          Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;          Data->min_dy = -(2 * 16 + 2 * (y) * 16);
1515  /*          if (Data->qpel) { //we measure in qpixels
1516  //What we do here is a complicated version of CheckCandidateDirect(0,0);                  Data->max_dx *= 2;
1517  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;
1518                    Data->min_dx *= 2;
1519  */                  Data->min_dy *= 2;
1520          Data.max_dx = 2 * pParam->width - 2 * (x) * 16;                  Data->referencemv = b_mb->qmvs;
1521          Data.max_dy = 2 * pParam->height - 2 * (y) * 16;          } else Data->referencemv = b_mb->mvs;
1522          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);  
1523    
1524          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1525                  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);
1526                  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;
1527                  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);
1528                  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;
1529    
1530                  if (( pMB->mvs[k].x > Data.max_dx ) || ( pMB->mvs[k].x < Data.min_dx )                  if ( ( pMB->b_mvs[k].x > Data->max_dx ) || ( pMB->b_mvs[k].x < Data->min_dx )
1531                          || ( pMB->mvs[k].y > Data.max_dy ) || ( pMB->mvs[k].y < Data.min_dy )                          || ( pMB->b_mvs[k].y > Data->max_dy ) || ( pMB->b_mvs[k].y < Data->min_dy )) {
                         || ( 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 )) {  
1532    
1533                          *best_sad = 256*4096; // in that case, we won't use direct mode                          *best_sad = 256*4096; // in that case, we won't use direct mode
1534                          pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"                          pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
1535                          pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;                          pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;
1536                          return 0;                          return 256*4096;
1537                  }                  }
1538                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1539                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1540                          pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];                          pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];
1541                          Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1542                          Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1543                          break;                          break;
1544                  }                  }
1545          }          }
1546    
1547          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V) CheckCandidate = CheckCandidateDirect;
                 CheckCandidate = CheckCandidateDirect;  
1548          else CheckCandidate = CheckCandidateDirectno4v;          else CheckCandidate = CheckCandidateDirectno4v;
1549    
1550          (*CheckCandidate)(0, 0, 255, &k, &Data);          (*CheckCandidate)(0, 0, 255, &k, Data);
   
 // skip decision  
         if (iMinSAD - 2 * lambda_vec16[iQuant] < (int32_t)iQuant * SKIP_THRESH_B) {  
                 //checking chroma. everything copied from MC  
                 //this is not full chroma compensation, only it's fullpel approximation. should work though  
                 int sum, dx, dy, b_dx, b_dy;  
   
                 sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;  
                 dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));  
   
                 sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;  
                 dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));  
1551    
1552                  sum = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;  // initial (fast) skip decision
1553                  b_dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));          if (*Data->iMinSAD < pMB->quant * INITIAL_SKIP_THRESH*2) {
1554                    SkipDecisionB(pCur, f_Ref, b_Ref, pMB, x, y, Data->chroma, Data); //possible skip - checking chroma
1555                  sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;                  if (pMB->mode == MODE_DIRECT_NONE_MV) return *Data->iMinSAD; // skip.
                 b_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));  
   
                 sum = sad8bi(pCur->u + 8*x + 8*y*(iEdgedWidth/2),  
                                         f_Ref->u + (y*8 + dy/2) * (iEdgedWidth/2) + x*8 + dx/2,  
                                         b_Ref->u + (y*8 + b_dy/2) * (iEdgedWidth/2) + x*8 + b_dx/2,  
                                         iEdgedWidth/2);  
                 sum += sad8bi(pCur->v + 8*x + 8*y*(iEdgedWidth/2),  
                                         f_Ref->v + (y*8 + dy/2) * (iEdgedWidth/2) + x*8 + dx/2,  
                                         b_Ref->v + (y*8 + b_dy/2) * (iEdgedWidth/2) + x*8 + b_dx/2,  
                                         iEdgedWidth/2);  
   
                 if ((uint32_t) sum < MAX_CHROMA_SAD_FOR_SKIP * Data.iQuant) {  
                         pMB->mode = MODE_DIRECT_NONE_MV;  
                         return iMinSAD;  
                 }  
1556          }          }
1557    
1558          skip_sad = iMinSAD;          skip_sad = *Data->iMinSAD;
1559    
1560  //  DIRECT MODE DELTA VECTOR SEARCH.  //  DIRECT MODE DELTA VECTOR SEARCH.
1561  //      This has to be made more effective, but at the moment I'm happy it's running at all  //      This has to be made more effective, but at the moment I'm happy it's running at all
# Line 1154  Line 1564 
1564                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1565                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1566    
1567          (*MainSearchPtr)(0, 0, &Data, 255);          (*MainSearchPtr)(0, 0, Data, 255);
1568    
1569          HalfpelRefine(&Data);          SubpelRefine(Data);
1570    
1571          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;  
1572    
1573          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V || Data->qpel) pMB->mode = MODE_DIRECT;
                 pMB->mode = MODE_DIRECT;  
1574          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1575    
1576          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1577    
1578          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1579                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1580                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = (     (Data->currentMV->x == 0)
1581                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1582                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          :pMB->mvs[k].x - Data->referencemv[k].x);
1583                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1584                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1585                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1586                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1587                    if (Data->qpel) {
1588                            pMB->qmvs[k].x = pMB->mvs[k].x; pMB->mvs[k].x /= 2;
1589                            pMB->b_qmvs[k].x = pMB->b_mvs[k].x; pMB->b_mvs[k].x /= 2;
1590                            pMB->qmvs[k].y = pMB->mvs[k].y; pMB->mvs[k].y /= 2;
1591                            pMB->b_qmvs[k].y = pMB->b_mvs[k].y; pMB->b_mvs[k].y /= 2;
1592                    }
1593    
1594                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1595                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1596                          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];
1597                            pMB->qmvs[3] = pMB->qmvs[2] = pMB->qmvs[1] = pMB->qmvs[0];
1598                            pMB->b_qmvs[3] = pMB->b_qmvs[2] = pMB->b_qmvs[1] = pMB->b_qmvs[0];
1599                          break;                          break;
1600                  }                  }
1601          }          }
1602          return 0;//skip_sad;          return skip_sad;
1603  }  }
1604    
1605  static __inline void  
1606    static void
1607  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const uint8_t * const f_Ref,
1608                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1609                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
# Line 1199  Line 1617 
1617                                  const uint32_t fcode,                                  const uint32_t fcode,
1618                                  const uint32_t bcode,                                  const uint32_t bcode,
1619                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1620                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1621                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1622                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1623                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1624                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1625                                    SearchData * const fData)
1626    
1627  {  {
 /* 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;  
1628    
1629          int iDirection, i, j;          int iDirection, i, j;
1630          int32_t iMinSAD = 256*4096;          SearchData bData;
         VECTOR currentMV[3];  
         SearchData fData, bData;  
1631    
1632          fData.iMinSAD = bData.iMinSAD = &iMinSAD;          fData->qpel_precision = 0;
1633            memcpy(&bData, fData, sizeof(SearchData)); //quick copy of common data
1634            *fData->iMinSAD = 4096*256;
1635            bData.currentMV++; bData.currentQMV++;
1636            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1637    
1638            i = (x + y * fData->iEdgedWidth) * 16;
1639            bData.bRef = fData->Ref = f_Ref + i;
1640            bData.bRefH = fData->RefH = f_RefH + i;
1641            bData.bRefV = fData->RefV = f_RefV + i;
1642            bData.bRefHV = fData->RefHV = f_RefHV + i;
1643            bData.Ref = fData->bRef = b_Ref + i;
1644            bData.RefH = fData->bRefH = b_RefH + i;
1645            bData.RefV = fData->bRefV = b_RefV + i;
1646            bData.RefHV = fData->bRefHV = b_RefHV + i;
1647    
1648            bData.bpredMV = fData->predMV = *f_predMV;
1649            fData->bpredMV = bData.predMV = *b_predMV;
1650            fData->currentMV[0] = fData->currentMV[2];
1651    
1652            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);
1653            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);
1654    
1655            if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1656            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dx;
1657            if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dy;
1658            if (fData->currentMV[0].y < fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1659    
1660            if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1661            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dx;
1662            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dy;
1663            if (fData->currentMV[1].y < bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1664    
1665          fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
         fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;  
         fData.currentMV = currentMV; bData.currentMV = currentMV + 1;  
         fData.iQuant = bData.iQuant = iQuant;  
         fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;  
   
         bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  
         bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;  
         bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;  
         bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;  
         bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;  
         bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;  
         bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;  
         bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;  
   
         bData.bpredMV = fData.predMV = *f_predMV;  
         fData.bpredMV = bData.predMV = *b_predMV;  
   
         currentMV[0] = pMB->mvs[0];  
         currentMV[1] = pMB->b_mvs[0];  
         get_range(&fData.min_dx, &fData.max_dx, &fData.min_dy, &fData.max_dy, x, y, 16, pParam->width, pParam->height, fcode);  
         get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode);  
   
         if (currentMV[0].x > fData.max_dx) currentMV[0].x = fData.max_dx;  
         if (currentMV[0].x < fData.min_dx) currentMV[0].x = fData.min_dy;  
         if (currentMV[0].y > fData.max_dy) currentMV[0].y = fData.max_dx;  
         if (currentMV[0].y > fData.min_dy) currentMV[0].y = fData.min_dy;  
   
         if (currentMV[1].x > bData.max_dx) currentMV[1].x = bData.max_dx;  
         if (currentMV[1].x < bData.min_dx) currentMV[1].x = bData.min_dy;  
         if (currentMV[1].y > bData.max_dy) currentMV[1].y = bData.max_dx;  
         if (currentMV[1].y > bData.min_dy) currentMV[1].y = bData.min_dy;  
   
         CheckCandidateInt(currentMV[0].x, currentMV[0].y, 255, &iDirection, &fData);  
1666    
1667  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)
1668    
1669          do {          do {
1670                  iDirection = 255;                  iDirection = 255;
1671                  // forward MV moves                  // forward MV moves
1672                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
1673    
1674                  CheckCandidateInt(i + 1, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1675                  CheckCandidateInt(i, j + 1, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1676                  CheckCandidateInt(i - 1, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1677                  CheckCandidateInt(i, j - 1, 0, &iDirection, &fData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
1678    
1679                  // backward MV moves                  // backward MV moves
1680                  i = currentMV[1].x; j = currentMV[1].y;                  i = fData->currentMV[1].x; j = fData->currentMV[1].y;
1681                  currentMV[2] = currentMV[0];                  fData->currentMV[2] = fData->currentMV[0];
   
1682                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1683                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1684                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
# Line 1279  Line 1686 
1686    
1687          } while (!(iDirection));          } while (!(iDirection));
1688    
1689  // two bits are needed to code interpolate mode. we treat the bits just like they were vector's          if (fData->qpel) {
1690          iMinSAD +=  2 * lambda_vec16[iQuant];                  if (*fData->iMinSAD > *best_sad + 500) return;
1691          if (iMinSAD < *best_sad) {                  CheckCandidate = CheckCandidateInt;
1692                  *best_sad = iMinSAD;                  fData->qpel_precision = bData.qpel_precision = 1;
1693                  pMB->mvs[0] = 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);
1694                  pMB->b_mvs[0] = currentMV[1];                  get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, 1, 0);
1695                    fData->currentQMV[2].x = fData->currentQMV[0].x = 2 * fData->currentMV[0].x;
1696                    fData->currentQMV[2].y = fData->currentQMV[0].y = 2 * fData->currentMV[0].y;
1697                    fData->currentQMV[1].x = 2 * fData->currentMV[1].x;
1698                    fData->currentQMV[1].y = 2 * fData->currentMV[1].y;
1699                    SubpelRefine(fData);
1700                    if (*fData->iMinSAD > *best_sad + 300) return;
1701                    fData->currentQMV[2] = fData->currentQMV[0];
1702                    SubpelRefine(&bData);
1703            }
1704    
1705            *fData->iMinSAD +=  (2+3) * fData->lambda16; // two bits are needed to code interpolate mode.
1706    
1707            if (*fData->iMinSAD < *best_sad) {
1708                    *best_sad = *fData->iMinSAD;
1709                    pMB->mvs[0] = fData->currentMV[0];
1710                    pMB->b_mvs[0] = fData->currentMV[1];
1711                  pMB->mode = MODE_INTERPOLATE;                  pMB->mode = MODE_INTERPOLATE;
1712                    if (fData->qpel) {
1713                            pMB->qmvs[0] = fData->currentQMV[0];
1714                            pMB->b_qmvs[0] = fData->currentQMV[1];
1715                            pMB->pmvs[1].x = pMB->qmvs[0].x - f_predMV->x;
1716                            pMB->pmvs[1].y = pMB->qmvs[0].y - f_predMV->y;
1717                            pMB->pmvs[0].x = pMB->b_qmvs[0].x - b_predMV->x;
1718                            pMB->pmvs[0].y = pMB->b_qmvs[0].y - b_predMV->y;
1719                    } else {
1720                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;
1721                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;
1722                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;
1723                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;
1724          }          }
1725  }  }
1726    }
1727    
1728  void  void
1729  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
# Line 1306  Line 1737 
1737                                           const IMAGE * const f_refV,                                           const IMAGE * const f_refV,
1738                                           const IMAGE * const f_refHV,                                           const IMAGE * const f_refHV,
1739                                           // backward (future) reference                                           // backward (future) reference
1740                                           const MACROBLOCK * const b_mbs,                                           const FRAMEINFO * const b_reference,
1741                                           const IMAGE * const b_ref,                                           const IMAGE * const b_ref,
1742                                           const IMAGE * const b_refH,                                           const IMAGE * const b_refH,
1743                                           const IMAGE * const b_refV,                                           const IMAGE * const b_refV,
1744                                           const IMAGE * const b_refHV)                                           const IMAGE * const b_refHV)
1745  {  {
1746          uint32_t i, j;          uint32_t i, j;
1747          int32_t best_sad, skip_sad;          int32_t best_sad;
1748            uint32_t skip_sad;
1749          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;
1750          static const VECTOR zeroMV={0,0};          static const VECTOR zeroMV={0,0};
1751            const MACROBLOCK * const b_mbs = b_reference->mbs;
1752    
1753          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
1754    
1755          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1756          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
1757    
1758          // note: i==horizontal, j==vertical  // some pre-inintialized data for the rest of the search
1759    
1760            SearchData Data;
1761            int32_t iMinSAD;
1762            VECTOR currentMV[3];
1763            VECTOR currentQMV[3];
1764            memset(&Data, 0, sizeof(SearchData));
1765            Data.iEdgedWidth = pParam->edged_width;
1766            Data.currentMV = currentMV; Data.currentQMV = currentQMV;
1767            Data.iMinSAD = &iMinSAD;
1768            Data.lambda16 = lambda_vec16[frame->quant];
1769            Data.chroma = frame->quant;
1770            Data.qpel = pParam->m_quarterpel;
1771            Data.rounding = 0;
1772    
1773            Data.RefQ = f_refV->u; // a good place, also used in MC (for similar purpose)
1774            // note: i==horizontal, j==vertical
1775          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
1776    
1777                  f_predMV = b_predMV = zeroMV;   /* prediction is reset at left boundary */                  f_predMV = b_predMV = zeroMV;   /* prediction is reset at left boundary */
# Line 1332  Line 1780 
1780                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;
1781                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;
1782    
1783  /* 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 */
1784                            if (b_reference->coding_type != S_VOP)
1785                          if (b_mb->mode == MODE_NOT_CODED) {                          if (b_mb->mode == MODE_NOT_CODED) {
1786                                  pMB->mode = MODE_NOT_CODED;                                  pMB->mode = MODE_NOT_CODED;
1787                                  continue;                                  continue;
1788                          }                          }
1789    
1790                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
1791                            pMB->quant = frame->quant;
1792    
1793  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
1794          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
   
1795                          skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,                          skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
1796                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,
1797                                                                          &frame->image,                                                                          &frame->image,
1798                                                                          i, j,                                                                          i, j,
1799                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
1800                                                                          TRB, TRD,                                                                          TRB, TRD,
1801                                                                          pParam,                                                                          pParam,
1802                                                                          pMB, b_mb,                                                                          pMB, b_mb,
1803                                                                          &best_sad);                                                                          &best_sad,
1804                                                                            &Data);
1805    
1806                          if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                          if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1807    
 //                      best_sad = 256*4096; //uncomment to disable Directsearch.  
 //      To disable any other mode, just comment the function call  
   
1808                          // forward search                          // forward search
1809                          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,
1810                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1811                                                  frame->motion_flags,                                                  frame->motion_flags,
1812                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
1813                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
1814                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
1815    
1816                          // backward search                          // backward search
1817                          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,
1818                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1819                                                  frame->motion_flags,                                                  frame->motion_flags,
1820                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
1821                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
1822                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
1823    
1824                          // 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
   
1825                          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,
1826                                                  b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                                                  b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
1827                                                  &frame->image,                                                  &frame->image,
1828                                                  i, j,                                                  i, j,
1829                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
1830                                                  frame->motion_flags,                                                  frame->motion_flags,
1831                                                  frame->quant, pParam,                                                  pParam,
1832                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
1833                                                  pMB, &best_sad);                                                  pMB, &best_sad,
1834                                                    &Data);
1835    
1836    // final skip decision
1837                            if ( (skip_sad < frame->quant * MAX_SAD00_FOR_SKIP*2)
1838                                            && ((100*best_sad)/(skip_sad+1) > FINAL_SKIP_THRESH) )
1839                                    SkipDecisionB(&frame->image, f_ref, b_ref, pMB,frame->quant, i, j, &Data);
1840    
1841                          switch (pMB->mode) {                          switch (pMB->mode) {
1842                                  case MODE_FORWARD:                                  case MODE_FORWARD:
1843                                          f_count++;                                          f_count++;
1844                                          f_predMV = pMB->mvs[0];                                          if (Data.qpel) f_predMV = pMB->qmvs[0];
1845                                            else f_predMV = pMB->mvs[0];
1846                                          break;                                          break;
1847                                  case MODE_BACKWARD:                                  case MODE_BACKWARD:
1848                                          b_count++;                                          b_count++;
1849                                          b_predMV = pMB->b_mvs[0];                                          if (Data.qpel) b_predMV = pMB->b_qmvs[0];
1850                                            else b_predMV = pMB->b_mvs[0];
1851                                          break;                                          break;
1852                                  case MODE_INTERPOLATE:                                  case MODE_INTERPOLATE:
1853                                          i_count++;                                          i_count++;
1854                                            if (Data.qpel) {
1855                                                    f_predMV = pMB->qmvs[0];
1856                                                    b_predMV = pMB->b_qmvs[0];
1857                                            } else {
1858                                          f_predMV = pMB->mvs[0];                                          f_predMV = pMB->mvs[0];
1859                                          b_predMV = pMB->b_mvs[0];                                          b_predMV = pMB->b_mvs[0];
1860                                            }
1861                                          break;                                          break;
1862                                  case MODE_DIRECT:                                  case MODE_DIRECT:
1863                                  case MODE_DIRECT_NO4V:                                  case MODE_DIRECT_NO4V:
1864                                          d_count++;                                          d_count++;
                                         break;  
1865                                  default:                                  default:
1866                                          break;                                          break;
1867                          }                          }
1868                  }                  }
1869          }          }
   
 //      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);  
   
1870  }  }
1871    
 /* Hinted ME starts here */  
   
1872  static __inline void  static __inline void
1873  Search8hinted(  const SearchData * const OldData,  MEanalyzeMB (   const uint8_t * const pRef,
1874                                  const int x, const int y,                                  const uint8_t * const pCur,
1875                                  const uint32_t MotionFlags,                                  const int x,
1876                                    const int y,
1877                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1878                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMBs,
1879                                  const MACROBLOCK * const pMBs,                                  SearchData * const Data)
                                 const int block)  
1880  {  {
         SearchData Data;  
         MainSearchFunc *MainSearchPtr;  
1881    
1882          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          int i, mask;
1883          Data.iMinSAD = OldData->iMinSAD + 1 + block;          VECTOR pmv[3];
1884          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));  
1885    
1886          CheckCandidate = CheckCandidate8;          for (i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
1887    
1888          if (block != 0)          //median is only used as prediction. it doesn't have to be real
1889                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *          if (x == 1 && y == 1) Data->predMV.x = Data->predMV.y = 0;
1890                                                                  d_mv_bits(      Data.currentMV->x - Data.predMV.x,          else
1891                                                                                          Data.currentMV->y - Data.predMV.y,                  if (x == 1) //left macroblock does not have any vector now
1892                                                                                          Data.iFcode);                          Data->predMV = (pMB - pParam->mb_width)->mvs[0]; // top instead of median
1893                    else if (y == 1) // top macroblock doesn't have it's vector
1894                            Data->predMV = (pMB - 1)->mvs[0]; // left instead of median
1895                            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); //else median
1896    
1897            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1898                                    pParam->width, pParam->height, Data->iFcode - pParam->m_quarterpel, 0, Data->rrv);
1899    
1900          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;
1901                                  pParam->width, pParam->height, OldData->iFcode);          Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
1902    
1903          if (pMB->mode == MODE_INTER4V) {          pmv[1].x = EVEN(pMB->mvs[0].x);
1904                  int dummy;          pmv[1].y = EVEN(pMB->mvs[0].y);
1905                  CheckCandidate8(pMB->mvs[block].x, pMB->mvs[block].y, 0, &dummy, &Data); }          pmv[2].x = EVEN(Data->predMV.x);
1906            pmv[2].y = EVEN(Data->predMV.y);
1907            pmv[0].x = pmv[0].y = 0;
1908    
1909          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;          CheckCandidate32I(0, 0, 255, &i, Data);
                 else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;  
                         else MainSearchPtr = DiamondSearch;  
1910    
1911          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);          if (*Data->iMinSAD > 4 * MAX_SAD00_FOR_SKIP * 4) {
1912    
1913          if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                  if (!(mask = make_mask(pmv, 1)))
1914                            CheckCandidate32I(pmv[1].x, pmv[1].y, mask, &i, Data);
1915                    if (!(mask = make_mask(pmv, 2)))
1916                            CheckCandidate32I(pmv[2].x, pmv[2].y, mask, &i, Data);
1917    
1918                    if (*Data->iMinSAD > 4 * MAX_SAD00_FOR_SKIP * 4) // diamond only if needed
1919                            DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
1920    
1921          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;                  for (i = 0; i < 4; i++) {
1922          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;                          MACROBLOCK * MB = &pMBs[x + (i&1) + (y+(i>>1) * pParam->mb_width)];
1923          pMB->mvs[block] = *(Data.currentMV);                          MB->mvs[0] = MB->mvs[1] = MB->mvs[2] = MB->mvs[3] = Data->currentMV[i];
1924          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                          MB->mode = MODE_INTER;
1925                            MB->sad16 = Data->iMinSAD[i+1];
1926                    }
1927            }
1928  }  }
1929    
1930    #define INTRA_BIAS              2500
1931    #define INTRA_THRESH    1500
1932    #define INTER_THRESH    1400
1933    
 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)  
 {  
1934    
1935          const int32_t iEdgedWidth = pParam->edged_width;  int
1936    MEanalysis(     const IMAGE * const pRef,
1937                            FRAMEINFO * const Current,
1938                            MBParam * const pParam,
1939                            int maxIntra, //maximum number if non-I frames
1940                            int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame
1941                            int bCount) // number if B frames in a row
1942    {
1943            uint32_t x, y, intra = 0;
1944            int sSAD = 0;
1945            MACROBLOCK * const pMBs = Current->mbs;
1946            const IMAGE * const pCurrent = &Current->image;
1947            int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH;
1948            const VECTOR zeroMV = {0,0};
1949    
1950          int i;          int32_t iMinSAD[5], temp[5];
1951          VECTOR currentMV[5];          VECTOR currentMV[5];
         int32_t iMinSAD[5];  
         int32_t temp[5];  
         MainSearchFunc * MainSearchPtr;  
1952          SearchData Data;          SearchData Data;
1953            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;  
1954          Data.currentMV = currentMV;          Data.currentMV = currentMV;
1955          Data.iMinSAD = iMinSAD;          Data.iMinSAD = iMinSAD;
1956          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data.iFcode = Current->fcode;
1957          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;  
1958          Data.temp = temp;          Data.temp = temp;
1959          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;  
   
         if (pMB->dquant != NO_CHANGE) inter4v = 0;  
   
         if (inter4v)  
                 CheckCandidate = CheckCandidate16;  
         else CheckCandidate = CheckCandidate16no4v;  
   
   
         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;  
1960    
1961          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          if (intraCount < 10) // we're right after an I frame
1962                    IntraThresh += 4 * (intraCount - 10) * (intraCount - 10);
1963            else
1964                    if ( 5*(maxIntra - intraCount) < maxIntra) // we're close to maximum. 2 sec when max is 10 sec
1965                            IntraThresh -= (IntraThresh * (maxIntra - 5*(maxIntra - intraCount)))/maxIntra;
1966    
1967          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          InterThresh += 400 * (1 - bCount);
1968            if (InterThresh < 300) InterThresh = 300;
1969    
1970          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);  
1971    
1972          if (!(inter4v) ||          for (y = 1; y < pParam->mb_height-1; y+=2) {
1973                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  for (x = 1; x < pParam->mb_width-1; x+=2) {
1974  // INTER MODE                          int i;
1975    
1976                  pMB->mode = MODE_INTER;                          if (bCount == 0) pMBs[x + y * pParam->mb_width].mvs[0] = zeroMV;
                 pMB->mvs[0] = pMB->mvs[1]  
                         = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];  
1977    
1978                  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];  
1979    
1980                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                          for (i = 0; i < 4; i++) {
1981                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                                  int dev;
1982          } else {                                  MACROBLOCK *pMB = &pMBs[x+(i&1) + y+(i>>1) * pParam->mb_width];
1983  // INTER4V MODE; all other things are already set in Search8hinted                                  if (pMB->sad16 > IntraThresh) {
1984                  pMB->mode = MODE_INTER4V;                                          dev = dev16(pCurrent->y + (x + (i&1) + (y + (i>>1))* pParam->edged_width) * 16,
1985                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                                                                            pParam->edged_width);
1986                                            if (dev + IntraThresh < pMB->sad16) {
1987                                                    pMB->mode = MODE_INTRA;
1988                                                    if (++intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return I_VOP;
1989          }          }
   
1990  }  }
1991                                    sSAD += pMB->sad16;
 void  
 MotionEstimationHinted( MBParam * const pParam,  
                                                 FRAMEINFO * const current,  
                                                 FRAMEINFO * const reference,  
                                                 const IMAGE * const pRefH,  
                                                 const IMAGE * const pRefV,  
                                                 const IMAGE * const pRefHV)  
 {  
         MACROBLOCK *const pMBs = current->mbs;  
         const IMAGE *const pCurrent = &current->image;  
         const IMAGE *const pRef = &reference->image;  
   
         uint32_t x, y;  
   
         if (sadInit) (*sadInit) ();  
   
         for (y = 0; y < pParam->mb_height; y++) {  
                 for (x = 0; x < pParam->mb_width; x++)  {  
   
                         MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];  
   
 //intra mode is copied from the first pass. At least for the time being  
                         if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;  
   
                         if (!(current->global_flags & XVID_LUMIMASKING)) {  
                                 pMB->dquant = NO_CHANGE;  
                                 pMB->quant = current->quant; }  
   
                         SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,  
                                                         y, current->motion_flags, pMB->quant,  
                                                         current->fcode, pParam, pMBs,  
                                                         current->global_flags & XVID_INTER4V, pMB);  
   
1992                  }                  }
1993          }          }
1994  }  }
1995            sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
1996            if (sSAD > IntraThresh + INTRA_BIAS ) return I_VOP;
1997            if (sSAD > InterThresh ) return P_VOP;
1998            emms();
1999            return B_VOP;
2000    
2001  static __inline int  }
 MEanalyzeMB (   const uint8_t * const pRef,  
                                 const uint8_t * const pCur,  
                                 const int x,  
                                 const int y,  
                                 const uint32_t iFcode,  
                                 const MBParam * const pParam,  
                                 const MACROBLOCK * const pMBs,  
                                 MACROBLOCK * const pMB)  
 {  
   
         const int32_t iEdgedWidth = pParam->edged_width;  
         int i, mask;  
         VECTOR currentMV, pmv[3];  
         int32_t iMinSAD = MV_MAX_ERROR;  
         SearchData Data;  
   
         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 + (x + y * iEdgedWidth) * 16;  
         Data.iEdgedWidth = iEdgedWidth;  
         Data.currentMV = &currentMV;  
         Data.iMinSAD = &iMinSAD;  
         Data.Ref = pRef + (x + iEdgedWidth*y)*16;  
         Data.iQuant = 2;  
         Data.iFcode = iFcode;  
   
         CheckCandidate = CheckCandidate16no4vI;  
   
         pmv[1].x = EVEN(pMB->mvs[0].x);  
         pmv[1].y = EVEN(pMB->mvs[0].y);  
         pmv[0].x = EVEN(Data.predMV.x);  
         pmv[0].y = EVEN(Data.predMV.y);  
         pmv[2].x = pmv[2].y = 0;  
   
         CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, &Data);  
         if (!(mask = make_mask(pmv, 1)))  
                 CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, &Data);  
         if (!(mask = make_mask(pmv, 2)))  
                 CheckCandidate16no4vI(0, 0, mask, &i, &Data);  
2002    
2003          DiamondSearch(currentMV.x, currentMV.y, &Data, i);  static void
2004    CheckGMC(int x, int y, const int dir, int * iDirection,
2005                    const MACROBLOCK * const pMBs, uint32_t * bestcount, VECTOR * GMC,
2006                    const MBParam * const pParam)
2007    {
2008            uint32_t mx, my, a, count = 0;
2009    
2010          pMB->mvs[0] = pMB->mvs[1]          for (my = 1; my < pParam->mb_height-1; my++)
2011                          = pMB->mvs[2] = pMB->mvs[3] = currentMV; // all, for future get_pmv()                  for (mx = 1; mx < pParam->mb_width-1; mx++) {
2012                            VECTOR mv;
2013                            const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2014                            if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED) continue;
2015                            mv = pMB->mvs[0];
2016                            a = ABS(mv.x - x) + ABS(mv.y - y);
2017                            if (a < 6) count += 6 - a;
2018                    }
2019    
2020          return iMinSAD;          if (count > *bestcount) {
2021                    *bestcount = count;
2022                    *iDirection = dir;
2023                    GMC->x = x; GMC->y = y;
2024            }
2025  }  }
2026    
 #define INTRA_THRESH    1350  
 #define INTER_THRESH    900  
2027    
2028  int  static VECTOR
2029  MEanalysis(     const IMAGE * const pRef,  GlobalMotionEst(const MACROBLOCK * const pMBs, const MBParam * const pParam, const uint32_t iFcode)
                         const IMAGE * const pCurrent,  
                         MBParam * const pParam,  
                         MACROBLOCK * const pMBs,  
                         const uint32_t iFcode)  
2030  {  {
         uint32_t x, y, intra = 0;  
         int sSAD = 0;  
2031    
2032          if (sadInit) (*sadInit) ();          uint32_t count, bestcount = 0;
2033            int x, y;
2034            VECTOR gmc = {0,0};
2035            int step, min_x, max_x, min_y, max_y;
2036            uint32_t mx, my;
2037            int iDirection, bDirection;
2038    
2039          for (y = 0; y < pParam->mb_height-1; y++) {          min_x = min_y = -32<<iFcode;
2040                  for (x = 0; x < pParam->mb_width; x++) {          max_x = max_y = 32<<iFcode;
                         int sad, dev;  
2041    
2042                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];  //step1: let's find a rough camera panning
2043            for (step = 32; step >= 2; step /= 2) {
2044                    bestcount = 0;
2045                    for (y = min_y; y <= max_y; y += step)
2046                            for (x = min_x ; x <= max_x; x += step) {
2047                                    count = 0;
2048                                    //for all macroblocks
2049                                    for (my = 1; my < pParam->mb_height-1; my++)
2050                                            for (mx = 1; mx < pParam->mb_width-1; mx++) {
2051                                                    const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2052                                                    VECTOR mv;
2053    
2054                          sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,                                                  if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
2055                                                                  iFcode, pParam, pMBs, pMB);                                                          continue;
2056    
2057                          if ( x != 0 && y != 0 && x != pParam->mb_width-1 ) { //no edge macroblocks, they just don't work                                                  mv = pMB->mvs[0];
2058                                  if (sad > INTRA_THRESH) {                                                  if ( ABS(mv.x - x) <= step && ABS(mv.y - y) <= step )   /* GMC translation is always halfpel-res */
2059                                          dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                                          count++;
                                                                   pParam->edged_width);  
                                         if (dev + INTRA_THRESH < sad) intra++;  
                                         if (intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame  
2060                                  }                                  }
2061                                  sSAD += sad;                                  if (count >= bestcount) { bestcount = count; gmc.x = x; gmc.y = y; }
2062                          }                          }
2063                    min_x = gmc.x - step;
2064                    max_x = gmc.x + step;
2065                    min_y = gmc.y - step;
2066                    max_y = gmc.y + step;
2067                  }                  }
2068    
2069            if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10)
2070                    gmc.x = gmc.y = 0; //no camara pan, no GMC
2071    
2072    // step2: let's refine camera panning using gradiend-descent approach
2073    // TODO: more warping points may be evaluated here (like in interpolate mode search - two vectors in one diamond)
2074            bestcount = 0;
2075            CheckGMC(gmc.x, gmc.y, 255, &iDirection, pMBs, &bestcount, &gmc, pParam);
2076            do {
2077                    x = gmc.x; y = gmc.y;
2078                    bDirection = iDirection; iDirection = 0;
2079                    if (bDirection & 1) CheckGMC(x - 1, y, 1+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2080                    if (bDirection & 2) CheckGMC(x + 1, y, 2+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2081                    if (bDirection & 4) CheckGMC(x, y - 1, 1+2+4, &iDirection, pMBs, &bestcount, &gmc, pParam);
2082                    if (bDirection & 8) CheckGMC(x, y + 1, 1+2+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2083    
2084            } while (iDirection);
2085    
2086            if (pParam->m_quarterpel) {
2087                    gmc.x *= 2;
2088                    gmc.y *= 2;     /* we store the halfpel value as pseudo-qpel to make comparison easier */
2089          }          }
         sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);  
         if (sSAD > INTER_THRESH ) return 1; //P frame  
         emms();  
         return 0; // B frame  
2090    
2091            return gmc;
2092  }  }

Legend:
Removed from v.539  
changed lines
  Added in v.754

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