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

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

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