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

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

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