[svn] / branches / dev-api-3 / xvidcore / src / motion / motion_est.c Repository:
ViewVC logotype

Diff of /branches/dev-api-3/xvidcore/src/motion/motion_est.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 530, Mon Sep 23 20:36:02 2002 UTC revision 836, Wed Feb 12 12:57:27 2003 UTC
# Line 31  Line 31 
31  #include <assert.h>  #include <assert.h>
32  #include <stdio.h>  #include <stdio.h>
33  #include <stdlib.h>  #include <stdlib.h>
34    #include <string.h>     // memcpy
35    #include <math.h>       // lrint
36    
37  #include "../encoder.h"  #include "../encoder.h"
38  #include "../utils/mbfunctions.h"  #include "../utils/mbfunctions.h"
39  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
40  #include "../global.h"  #include "../global.h"
41  #include "../utils/timer.h"  #include "../utils/timer.h"
42    #include "../image/interpolate8x8.h"
43  #include "motion_est.h"  #include "motion_est.h"
44  #include "motion.h"  #include "motion.h"
45  #include "sad.h"  #include "sad.h"
46    #include "../utils/emms.h"
47    #include "../dct/fdct.h"
48    
49  #define INITIAL_SKIP_THRESH     (10)  #define INITIAL_SKIP_THRESH     (10)
50  #define FINAL_SKIP_THRESH       (50)  #define FINAL_SKIP_THRESH       (50)
51  #define MAX_SAD00_FOR_SKIP      (20)  #define MAX_SAD00_FOR_SKIP      (20)
52  #define MAX_CHROMA_SAD_FOR_SKIP (18)  #define MAX_CHROMA_SAD_FOR_SKIP (22)
 #define SKIP_THRESH_B (10)  
53    
54  #define CHECK_CANDIDATE(X,Y,D) { \  #define CHECK_CANDIDATE(X,Y,D) { \
55  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }  CheckCandidate((X),(Y), (D), &iDirection, data ); }
56    
57  #define iDiamondSize 2  static __inline uint32_t
58    d_mv_bits(int x, int y, const VECTOR pred, const uint32_t iFcode, const int qpel, const int rrv)
 //FILE * debug;  
   
 static __inline int  
 d_mv_bits(int x, int y, const uint32_t iFcode)  
59  {  {
60          int xb, yb;          int xb, yb;
61            x = qpel ? x<<1 : x;
62            y = qpel ? y<<1 : y;
63            if (rrv) { x = RRV_MV_SCALEDOWN(x); y = RRV_MV_SCALEDOWN(y); }
64    
65          if (x == 0) xb = 1;          x -= pred.x;
66          else {          y -= pred.y;
67                  if (x < 0) x = -x;  
68            if (x) {
69                    x = ABS(x);
70                  x += (1 << (iFcode - 1)) - 1;                  x += (1 << (iFcode - 1)) - 1;
71                  x >>= (iFcode - 1);                  x >>= (iFcode - 1);
72                  if (x > 32) x = 32;                  if (x > 32) x = 32;
73                  xb = mvtab[x] + iFcode;                  xb = mvtab[x] + iFcode;
74          }          } else xb = 1;
75    
76          if (y == 0) yb = 1;          if (y) {
77          else {                  y = ABS(y);
                 if (y < 0) y = -y;  
78                  y += (1 << (iFcode - 1)) - 1;                  y += (1 << (iFcode - 1)) - 1;
79                  y >>= (iFcode - 1);                  y >>= (iFcode - 1);
80                  if (y > 32) y = 32;                  if (y > 32) y = 32;
81                  yb = mvtab[y] + iFcode;                  yb = mvtab[y] + iFcode;
82          }          } else yb = 1;
83          return xb + yb;          return xb + yb;
84  }  }
85    
86  /* CHACK_CANDIATE FUNCTIONS START */  static int32_t ChromaSAD2(int fx, int fy, int bx, int by, const SearchData * const data)
87    {
88            int sad;
89            const uint32_t stride = data->iEdgedWidth/2;
90            uint8_t * f_refu = data->RefQ,
91                    * f_refv = data->RefQ + 8,
92                    * b_refu = data->RefQ + 16,
93                    * b_refv = data->RefQ + 24;
94    
95            switch (((fx & 1) << 1) | (fy & 1))     {
96                    case 0:
97                            fx = fx / 2; fy = fy / 2;
98                            f_refu = (uint8_t*)data->RefCU + fy * stride + fx, stride;
99                            f_refv = (uint8_t*)data->RefCV + fy * stride + fx, stride;
100                            break;
101                    case 1:
102                            fx = fx / 2; fy = (fy - 1) / 2;
103                            interpolate8x8_halfpel_v(f_refu, data->RefCU + fy * stride + fx, stride, data->rounding);
104                            interpolate8x8_halfpel_v(f_refv, data->RefCV + fy * stride + fx, stride, data->rounding);
105                            break;
106                    case 2:
107                            fx = (fx - 1) / 2; fy = fy / 2;
108                            interpolate8x8_halfpel_h(f_refu, data->RefCU + fy * stride + fx, stride, data->rounding);
109                            interpolate8x8_halfpel_h(f_refv, data->RefCV + fy * stride + fx, stride, data->rounding);
110                            break;
111                    default:
112                            fx = (fx - 1) / 2; fy = (fy - 1) / 2;
113                            interpolate8x8_halfpel_hv(f_refu, data->RefCU + fy * stride + fx, stride, data->rounding);
114                            interpolate8x8_halfpel_hv(f_refv, data->RefCV + fy * stride + fx, stride, data->rounding);
115                            break;
116            }
117    
118            switch (((bx & 1) << 1) | (by & 1))     {
119                    case 0:
120                            bx = bx / 2; by = by / 2;
121                            b_refu = (uint8_t*)data->b_RefCU + by * stride + bx, stride;
122                            b_refv = (uint8_t*)data->b_RefCV + by * stride + bx, stride;
123                            break;
124                    case 1:
125                            bx = bx / 2; by = (by - 1) / 2;
126                            interpolate8x8_halfpel_v(b_refu, data->b_RefCU + by * stride + bx, stride, data->rounding);
127                            interpolate8x8_halfpel_v(b_refv, data->b_RefCV + by * stride + bx, stride, data->rounding);
128                            break;
129                    case 2:
130                            bx = (bx - 1) / 2; by = by / 2;
131                            interpolate8x8_halfpel_h(b_refu, data->b_RefCU + by * stride + bx, stride, data->rounding);
132                            interpolate8x8_halfpel_h(b_refv, data->b_RefCV + by * stride + bx, stride, data->rounding);
133                            break;
134                    default:
135                            bx = (bx - 1) / 2; by = (by - 1) / 2;
136                            interpolate8x8_halfpel_hv(b_refu, data->b_RefCU + by * stride + bx, stride, data->rounding);
137                            interpolate8x8_halfpel_hv(b_refv, data->b_RefCV + by * stride + bx, stride, data->rounding);
138                            break;
139            }
140    
141            sad = sad8bi(data->CurU, b_refu, f_refu, stride);
142            sad += sad8bi(data->CurV, b_refv, f_refv, stride);
143    
144            return sad;
145    }
146    
147    
148    static int32_t
149    ChromaSAD(int dx, int dy, const SearchData * const data)
150    {
151            int sad;
152            const uint32_t stride = data->iEdgedWidth/2;
153    
154            if (dx == data->temp[5] && dy == data->temp[6]) return data->temp[7]; //it has been checked recently
155            data->temp[5] = dx; data->temp[6] = dy; // backup
156    
157            switch (((dx & 1) << 1) | (dy & 1))     {
158                    case 0:
159                            dx = dx / 2; dy = dy / 2;
160                            sad = sad8(data->CurU, data->RefCU + dy * stride + dx, stride);
161                            sad += sad8(data->CurV, data->RefCV + dy * stride + dx, stride);
162                            break;
163                    case 1:
164                            dx = dx / 2; dy = (dy - 1) / 2;
165                            sad = sad8bi(data->CurU, data->RefCU + dy * stride + dx, data->RefCU + (dy+1) * stride + dx, stride);
166                            sad += sad8bi(data->CurV, data->RefCV + dy * stride + dx, data->RefCV + (dy+1) * stride + dx, stride);
167                            break;
168                    case 2:
169                            dx = (dx - 1) / 2; dy = dy / 2;
170                            sad = sad8bi(data->CurU, data->RefCU + dy * stride + dx, data->RefCU + dy * stride + dx+1, stride);
171                            sad += sad8bi(data->CurV, data->RefCV + dy * stride + dx, data->RefCV + dy * stride + dx+1, stride);
172                            break;
173                    default:
174                            dx = (dx - 1) / 2; dy = (dy - 1) / 2;
175                            interpolate8x8_halfpel_hv(data->RefQ, data->RefCU + dy * stride + dx, stride, data->rounding);
176                            sad = sad8(data->CurU, data->RefQ, stride);
177    
178                            interpolate8x8_halfpel_hv(data->RefQ, data->RefCV + dy * stride + dx, stride, data->rounding);
179                            sad += sad8(data->CurV, data->RefQ, stride);
180                            break;
181            }
182            data->temp[7] = sad; //backup, part 2
183            return sad;
184    }
185    
186    static __inline const uint8_t *
187    GetReferenceB(const int x, const int y, const uint32_t dir, const SearchData * const data)
188    {
189    //      dir : 0 = forward, 1 = backward
190            switch ( (dir << 2) | ((x&1)<<1) | (y&1) ) {
191                    case 0 : return data->Ref + x/2 + (y/2)*(data->iEdgedWidth);
192                    case 1 : return data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth);
193                    case 2 : return data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth);
194                    case 3 : return data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth);
195                    case 4 : return data->bRef + x/2 + (y/2)*(data->iEdgedWidth);
196                    case 5 : return data->bRefV + x/2 + ((y-1)/2)*(data->iEdgedWidth);
197                    case 6 : return data->bRefH + (x-1)/2 + (y/2)*(data->iEdgedWidth);
198                    default : return data->bRefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth);
199            }
200    }
201    
202    // this is a simpler copy of GetReferenceB, but as it's __inline anyway, we can keep the two separate
203    static __inline const uint8_t *
204    GetReference(const int x, const int y, const SearchData * const data)
205    {
206            switch ( ((x&1)<<1) | (y&1) ) {
207                    case 0 : return data->Ref + x/2 + (y/2)*(data->iEdgedWidth);
208                    case 3 : return data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth);
209                    case 1 : return data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth);
210                    default : return data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth);      //case 2
211            }
212    }
213    
214    static uint8_t *
215    Interpolate8x8qpel(const int x, const int y, const uint32_t block, const uint32_t dir, const SearchData * const data)
216    {
217    // create or find a qpel-precision reference picture; return pointer to it
218            uint8_t * Reference = data->RefQ + 16*dir;
219            const uint32_t iEdgedWidth = data->iEdgedWidth;
220            const uint32_t rounding = data->rounding;
221            const int halfpel_x = x/2;
222            const int halfpel_y = y/2;
223            const uint8_t *ref1, *ref2, *ref3, *ref4;
224    
225            ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
226            ref1 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
227            switch( ((x&1)<<1) + (y&1) ) {
228            case 0: // pure halfpel position
229                    return (uint8_t *) ref1;
230                    break;
231    
232            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
233                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
234                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
235                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
236                    break;
237    
238            case 2: // x qpel, y halfpel - left or right during qpel refinement
239                    ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
240                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
241                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
242                    break;
243    
244            default: // x and y in qpel resolution - the "corners" (top left/right and
245                             // bottom left/right) during qpel refinement
246                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
247                    ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
248                    ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
249                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
250                    ref3 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
251                    ref4 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
252                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
253                    break;
254            }
255            return Reference;
256    }
257    
258    static uint8_t *
259    Interpolate16x16qpel(const int x, const int y, const uint32_t dir, const SearchData * const data)
260    {
261    // create or find a qpel-precision reference picture; return pointer to it
262            uint8_t * Reference = data->RefQ + 16*dir;
263            const uint32_t iEdgedWidth = data->iEdgedWidth;
264            const uint32_t rounding = data->rounding;
265            const int halfpel_x = x/2;
266            const int halfpel_y = y/2;
267            const uint8_t *ref1, *ref2, *ref3, *ref4;
268    
269            ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
270            switch( ((x&1)<<1) + (y&1) ) {
271            case 3: // x and y in qpel resolution - the "corners" (top left/right and
272                             // bottom left/right) during qpel refinement
273                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
274                    ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
275                    ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
276                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
277                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
278                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
279                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
280                    break;
281    
282            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
283                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
284                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
285                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
286                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
287                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
288                    break;
289    
290            case 2: // x qpel, y halfpel - left or right during qpel refinement
291                    ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
292                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
293                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
294                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
295                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
296                    break;
297    
298            case 0: // pure halfpel position
299                    return (uint8_t *) ref1;
300            }
301            return Reference;
302    }
303    
304    /* CHECK_CANDIATE FUNCTIONS START */
305    
306  static void  static void
307  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)
308  {  {
309          int32_t * const sad = data->temp;          int xc, yc;
 //      static int32_t sad[5];  
         int t;  
310          const uint8_t * Reference;          const uint8_t * Reference;
311            VECTOR * current;
312            int32_t sad; uint32_t t;
313    
314          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
315                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
316    
317          switch ( ((x&1)<<1) + (y&1) ) {          if (!data->qpel_precision) {
318                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;                  Reference = GetReference(x, y, data);
319                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  current = data->currentMV;
320                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;                  xc = x; yc = y;
321                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;          } else { // x and y are in 1/4 precision
322                    Reference = Interpolate16x16qpel(x, y, 0, data);
323                    xc = x/2; yc = y/2; //for chroma sad
324                    current = data->currentQMV;
325            }
326    
327            sad = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
328            t = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
329    
330            sad += (data->lambda16 * t * sad)>>10;
331            data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))>>10;
332    
333            if (data->chroma) sad += ChromaSAD((xc >> 1) + roundtab_79[xc & 0x3],
334                                                                                                            (yc >> 1) + roundtab_79[yc & 0x3], data);
335    
336            if (sad < data->iMinSAD[0]) {
337                    data->iMinSAD[0] = sad;
338                    current[0].x = x; current[0].y = y;
339                    *dir = Direction;
340            }
341    
342            if (data->temp[1] < data->iMinSAD[1]) {
343                    data->iMinSAD[1] = data->temp[1]; current[1].x = x; current[1].y = y; }
344            if (data->temp[2] < data->iMinSAD[2]) {
345                    data->iMinSAD[2] = data->temp[2]; current[2].x = x; current[2].y = y; }
346            if (data->temp[3] < data->iMinSAD[3]) {
347                    data->iMinSAD[3] = data->temp[3]; current[3].x = x; current[3].y = y; }
348            if (data->temp[4] < data->iMinSAD[4]) {
349                    data->iMinSAD[4] = data->temp[4]; current[4].x = x; current[4].y = y; }
350    
351    }
352    
353    static void
354    CheckCandidate8(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
355    {
356            int32_t sad; uint32_t t;
357            const uint8_t * Reference;
358    
359            if ( (x > data->max_dx) || (x < data->min_dx)
360                    || (y > data->max_dy) || (y < data->min_dy) ) return;
361    
362            if (!data->qpel_precision) Reference = GetReference(x, y, data);
363            else Reference = Interpolate8x8qpel(x, y, 0, 0, data);
364    
365            sad = sad8(data->Cur, Reference, data->iEdgedWidth);
366            t = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
367    
368            sad += (data->lambda8 * t * (sad+NEIGH_8X8_BIAS))>>10;
369    
370            if (sad < *(data->iMinSAD)) {
371                    *(data->iMinSAD) = sad;
372                    data->currentMV->x = x; data->currentMV->y = y;
373                    *dir = Direction;
374          }          }
375    }
376    
377    
378    static void
379    CheckCandidate32(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
380    {
381            uint32_t t;
382            const uint8_t * Reference;
383    
384            if ( (!(x&1) && x !=0) || (!(y&1) && y !=0) || //non-zero integer value
385                    (x > data->max_dx) || (x < data->min_dx)
386                    || (y > data->max_dy) || (y < data->min_dy) ) return;
387    
388          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, sad+1);          Reference = GetReference(x, y, data);
389            t = d_mv_bits(x, y, data->predMV, data->iFcode, 0, 1);
390    
391          t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          data->temp[0] = sad32v_c(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
392          data->temp[0] += lambda_vec16[data->iQuant] * t;  
393          data->temp[1] += lambda_vec8[data->iQuant] * t;          data->temp[0] += (data->lambda16 * t * data->temp[0]) >> 10;
394            data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))>>10;
395    
396          if (data->temp[0] < data->iMinSAD[0]) {          if (data->temp[0] < data->iMinSAD[0]) {
397                  data->iMinSAD[0] = data->temp[0];                  data->iMinSAD[0] = data->temp[0];
# Line 118  Line 406 
406                  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; }
407          if (data->temp[4] < data->iMinSAD[4]) {          if (data->temp[4] < data->iMinSAD[4]) {
408                  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; }
   
409  }  }
410    
411  static void  static void
412  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)
413  {  {
414          int32_t sad;          int32_t sad, xc, yc;
415          const uint8_t * Reference;          const uint8_t * Reference;
416            uint32_t t;
417            VECTOR * current;
418    
419          if (( x > data->max_dx) || ( x < data->min_dx)          if ( (x > data->max_dx) | ( x < data->min_dx)
420                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  | (y > data->max_dy) | (y < data->min_dy) ) return;
421    
422          switch ( ((x&1)<<1) + (y&1) )          if (data->rrv && (!(x&1) && x !=0) | (!(y&1) && y !=0) ) return; //non-zero even value
423          {  
424                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;          if (data->qpel_precision) { // x and y are in 1/4 precision
425                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  Reference = Interpolate16x16qpel(x, y, 0, data);
426                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;                  current = data->currentQMV;
427                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  xc = x/2; yc = y/2;
428            } else {
429                    Reference = GetReference(x, y, data);
430                    current = data->currentMV;
431                    xc = x; yc = y;
432          }          }
433            t = d_mv_bits(x, y, data->predMV, data->iFcode,
434                                            data->qpel^data->qpel_precision, data->rrv);
435    
436          sad = lambda_vec16[data->iQuant] *          sad = sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);
437                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          sad += (data->lambda16 * t * sad)>>10;
438          sad += sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);  
439            if (data->chroma) sad += ChromaSAD((xc >> 1) + roundtab_79[xc & 0x3],
440                                                                                    (yc >> 1) + roundtab_79[yc & 0x3], data);
441    
442          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
443                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
444                  data->currentMV[0].x = x; data->currentMV[0].y = y;                  current->x = x; current->y = y;
445                  *dir = Direction; }                  *dir = Direction;
446            }
447  }  }
448    
449  static void  static void
450  CheckCandidateInt(const int xf, const int yf, const int Direction, int * const dir, const SearchData * const data)  CheckCandidate32I(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
451  {  {
452    // maximum speed - for P/B/I decision
453          int32_t sad;          int32_t sad;
         const int xb = data->currentMV[1].x;  
         const int yb = data->currentMV[1].y;  
         const uint8_t *ReferenceF, *ReferenceB;  
454    
455          if (( xf > data->max_dx) || ( xf < data->min_dx)          if ( (x > data->max_dx) || (x < data->min_dx)
456                  || ( yf > data->max_dy) || (yf < data->min_dy)) return;                  || (y > data->max_dy) || (y < data->min_dy) ) return;
457    
458            sad = sad32v_c(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),
459                                                            data->iEdgedWidth, data->temp+1);
460    
461          switch ( ((xf&1)<<1) + (yf&1) ) {          if (sad < *(data->iMinSAD)) {
462                  case 0 : ReferenceF = data->Ref + xf/2 + (yf/2)*(data->iEdgedWidth); break;                  *(data->iMinSAD) = sad;
463                  case 1 : ReferenceF = data->RefV + xf/2 + ((yf-1)/2)*(data->iEdgedWidth); break;                  data->currentMV[0].x = x; data->currentMV[0].y = y;
464                  case 2 : ReferenceF = data->RefH + (xf-1)/2 + (yf/2)*(data->iEdgedWidth); break;                  *dir = Direction;
                 default : ReferenceF = data->RefHV + (xf-1)/2 + ((yf-1)/2)*(data->iEdgedWidth); break;  
465          }          }
466            if (data->temp[1] < data->iMinSAD[1]) {
467                    data->iMinSAD[1] = data->temp[1]; data->currentMV[1].x = x; data->currentMV[1].y = y; }
468            if (data->temp[2] < data->iMinSAD[2]) {
469                    data->iMinSAD[2] = data->temp[2]; data->currentMV[2].x = x; data->currentMV[2].y = y; }
470            if (data->temp[3] < data->iMinSAD[3]) {
471                    data->iMinSAD[3] = data->temp[3]; data->currentMV[3].x = x; data->currentMV[3].y = y; }
472            if (data->temp[4] < data->iMinSAD[4]) {
473                    data->iMinSAD[4] = data->temp[4]; data->currentMV[4].x = x; data->currentMV[4].y = y; }
474    
         switch ( ((xb&1)<<1) + (yb&1) ) {  
                 case 0 : ReferenceB = data->bRef + xb/2 + (yb/2)*(data->iEdgedWidth); break;  
                 case 1 : ReferenceB = data->bRefV + xb/2 + ((yb-1)/2)*(data->iEdgedWidth); break;  
                 case 2 : ReferenceB = data->bRefH + (xb-1)/2 + (yb/2)*(data->iEdgedWidth); break;  
                 default : ReferenceB = data->bRefHV + (xb-1)/2 + ((yb-1)/2)*(data->iEdgedWidth); break;  
475          }          }
476    
477          sad = lambda_vec16[data->iQuant] *  static void
478                          ( d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode) +  CheckCandidateInt(const int xf, const int yf, const int Direction, int * const dir, const SearchData * const data)
479                            d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode) );  {
480            int32_t sad, xb, yb, xcf, ycf, xcb, ycb;
481            uint32_t t;
482            const uint8_t *ReferenceF, *ReferenceB;
483            VECTOR *current;
484    
485            if ( (xf > data->max_dx) | (xf < data->min_dx)
486                    | (yf > data->max_dy) | (yf < data->min_dy) ) return;
487    
488          sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);          if (!data->qpel_precision) {
489                    ReferenceF = GetReference(xf, yf, data);
490                    xb = data->currentMV[1].x; yb = data->currentMV[1].y;
491                    ReferenceB = GetReferenceB(xb, yb, 1, data);
492                    current = data->currentMV;
493                    xcf = xf; ycf = yf;
494                    xcb = xb; ycb = yb;
495            } else {
496                    ReferenceF = Interpolate16x16qpel(xf, yf, 0, data);
497                    xb = data->currentQMV[1].x; yb = data->currentQMV[1].y;
498                    current = data->currentQMV;
499                    ReferenceB = Interpolate16x16qpel(xb, yb, 1, data);
500                    xcf = xf/2; ycf = yf/2;
501                    xcb = xb/2; ycb = yb/2;
502            }
503    
504            t = d_mv_bits(xf, yf, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0)
505                     + d_mv_bits(xb, yb, data->bpredMV, data->iFcode, data->qpel^data->qpel_precision, 0);
506    
507            sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
508            sad += (data->lambda16 * t * sad)>>10;
509    
510            if (data->chroma) sad += ChromaSAD2((xcf >> 1) + roundtab_79[xcf & 0x3],
511                                                                                    (ycf >> 1) + roundtab_79[ycf & 0x3],
512                                                                                    (xcb >> 1) + roundtab_79[xcb & 0x3],
513                                                                                    (ycb >> 1) + roundtab_79[ycb & 0x3], data);
514    
515          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
516                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
517                  data->currentMV->x = xf; data->currentMV->y = yf;                  current->x = xf; current->y = yf;
518                  *dir = Direction; }                  *dir = Direction;
519            }
520  }  }
521    
522  static void  static void
523  CheckCandidateDirect(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidateDirect(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
524  {  {
525          int32_t sad;          int32_t sad = 0, xcf = 0, ycf = 0, xcb = 0, ycb = 0;
526          int k;          uint32_t k;
527          const uint8_t *ReferenceF;          const uint8_t *ReferenceF;
528          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
529          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
530    
531          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;          if (( x > 31) | ( x < -32) | ( y > 31) | (y < -32)) return;
   
         sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);  
532    
533          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
534                  mvs.x = data->directmvF[k].x + x;                  mvs.x = data->directmvF[k].x + x;
# Line 209  Line 541 
541                          data->directmvB[k].y                          data->directmvB[k].y
542                          : mvs.y - data->referencemv[k].y);                          : mvs.y - data->referencemv[k].y);
543    
544                  if (( mvs.x > data->max_dx ) || ( mvs.x < data->min_dx )                  if ( (mvs.x > data->max_dx) | (mvs.x < data->min_dx)
545                          || ( mvs.y > data->max_dy ) || ( mvs.y < data->min_dy )                          | (mvs.y > data->max_dy) | (mvs.y < data->min_dy)
546                          || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )                          | (b_mvs.x > data->max_dx) | (b_mvs.x < data->min_dx)
547                          || ( b_mvs.y > data->max_dy ) || ( b_mvs.y < data->min_dy )) return;                          | (b_mvs.y > data->max_dy) | (b_mvs.y < data->min_dy) ) return;
548    
549                  switch ( ((mvs.x&1)<<1) + (mvs.y&1) ) {                  if (data->qpel) {
550                          case 0 : ReferenceF = data->Ref + mvs.x/2 + (mvs.y/2)*(data->iEdgedWidth); break;                          xcf += mvs.x/2; ycf += mvs.y/2;
551                          case 1 : ReferenceF = data->RefV + mvs.x/2 + ((mvs.y-1)/2)*(data->iEdgedWidth); break;                          xcb += b_mvs.x/2; ycb += b_mvs.y/2;
552                          case 2 : ReferenceF = data->RefH + (mvs.x-1)/2 + (mvs.y/2)*(data->iEdgedWidth); break;                  } else {
553                          default : ReferenceF = data->RefHV + (mvs.x-1)/2 + ((mvs.y-1)/2)*(data->iEdgedWidth); break;                          xcf += mvs.x; ycf += mvs.y;
554                  }                          xcb += b_mvs.x; ycb += b_mvs.y;
555                            mvs.x *= 2; mvs.y *= 2; //we move to qpel precision anyway
556                  switch ( ((b_mvs.x&1)<<1) + (b_mvs.y&1) ) {                          b_mvs.x *= 2; b_mvs.y *= 2;
                         case 0 : ReferenceB = data->bRef + b_mvs.x/2 + (b_mvs.y/2)*(data->iEdgedWidth); break;  
                         case 1 : ReferenceB = data->bRefV + b_mvs.x/2 + ((b_mvs.y-1)/2)*(data->iEdgedWidth); break;  
                         case 2 : ReferenceB = data->bRefH + (b_mvs.x-1)/2 + (b_mvs.y/2)*(data->iEdgedWidth); break;  
                         default : ReferenceB = data->bRefHV + (b_mvs.x-1)/2 + ((b_mvs.y-1)/2)*(data->iEdgedWidth); break;  
557                  }                  }
558    
559                    ReferenceF = Interpolate8x8qpel(mvs.x, mvs.y, k, 0, data);
560                    ReferenceB = Interpolate8x8qpel(b_mvs.x, b_mvs.y, k, 1, data);
561    
562                  sad += sad8bi(data->Cur + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),                  sad += sad8bi(data->Cur + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
563                                                  ReferenceF + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),                                                  ReferenceF, ReferenceB, data->iEdgedWidth);
                                                 ReferenceB + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),  
                                                 data->iEdgedWidth);  
564                  if (sad > *(data->iMinSAD)) return;                  if (sad > *(data->iMinSAD)) return;
565          }          }
566    
567            sad += (data->lambda16 * d_mv_bits(x, y, zeroMV, 1, 0, 0) * sad)>>10;
568    
569            if (data->chroma) sad += ChromaSAD2((xcf >> 3) + roundtab_76[xcf & 0xf],
570                                                                                    (ycf >> 3) + roundtab_76[ycf & 0xf],
571                                                                                    (xcb >> 3) + roundtab_76[xcb & 0xf],
572                                                                                    (ycb >> 3) + roundtab_76[ycb & 0xf], data);
573    
574          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
575                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
576                  data->currentMV->x = x; data->currentMV->y = y;                  data->currentMV->x = x; data->currentMV->y = y;
577                  *dir = Direction; }                  *dir = Direction;
578            }
579  }  }
580    
581  static void  static void
582  CheckCandidateDirectno4v(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidateDirectno4v(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
583  {  {
584          int32_t sad;          int32_t sad, xcf, ycf, xcb, ycb;
585          const uint8_t *ReferenceF;          const uint8_t *ReferenceF;
586          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
587          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
588    
589          if (( x > 31) || ( x < -31) || ( y > 31) || (y < -31)) return;          if (( x > 31) | ( x < -32) | ( y > 31) | (y < -32)) return;
   
                 sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);  
590    
591          mvs.x = data->directmvF[0].x + x;          mvs.x = data->directmvF[0].x + x;
592          b_mvs.x = ((x == 0) ?          b_mvs.x = ((x == 0) ?
# Line 263  Line 598 
598                  data->directmvB[0].y                  data->directmvB[0].y
599                  : mvs.y - data->referencemv[0].y);                  : mvs.y - data->referencemv[0].y);
600    
601          if (( mvs.x > data->max_dx ) || ( mvs.x < data->min_dx )          if ( (mvs.x > data->max_dx) | (mvs.x < data->min_dx)
602                  || ( mvs.y > data->max_dy ) || ( mvs.y < data->min_dy )                  | (mvs.y > data->max_dy) | (mvs.y < data->min_dy)
603                  || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )                  | (b_mvs.x > data->max_dx) | (b_mvs.x < data->min_dx)
604                  || ( b_mvs.y > data->max_dy ) || ( b_mvs.y < data->min_dy )) return;                  | (b_mvs.y > data->max_dy) | (b_mvs.y < data->min_dy) ) return;
605    
606          switch ( ((mvs.x&1)<<1) + (mvs.y&1) ) {          if (data->qpel) {
607                  case 0 : ReferenceF = data->Ref + mvs.x/2 + (mvs.y/2)*(data->iEdgedWidth); break;                  xcf = 4*(mvs.x/2); ycf = 4*(mvs.y/2);
608                  case 1 : ReferenceF = data->RefV + mvs.x/2 + ((mvs.y-1)/2)*(data->iEdgedWidth); break;                  xcb = 4*(b_mvs.x/2); ycb = 4*(b_mvs.y/2);
609                  case 2 : ReferenceF = data->RefH + (mvs.x-1)/2 + (mvs.y/2)*(data->iEdgedWidth); break;                  ReferenceF = Interpolate16x16qpel(mvs.x, mvs.y, 0, data);
610                  default : ReferenceF = data->RefHV + (mvs.x-1)/2 + ((mvs.y-1)/2)*(data->iEdgedWidth); break;                  ReferenceB = Interpolate16x16qpel(b_mvs.x, b_mvs.y, 1, data);
611          }          } else {
612                    xcf = 4*mvs.x; ycf = 4*mvs.y;
613          switch ( ((b_mvs.x&1)<<1) + (b_mvs.y&1) ) {                  xcb = 4*b_mvs.x; ycb = 4*b_mvs.y;
614                  case 0 : ReferenceB = data->bRef + b_mvs.x/2 + (b_mvs.y/2)*(data->iEdgedWidth); break;                  ReferenceF = GetReference(mvs.x, mvs.y, data);
615                  case 1 : ReferenceB = data->bRefV + b_mvs.x/2 + ((b_mvs.y-1)/2)*(data->iEdgedWidth); break;                  ReferenceB = GetReferenceB(b_mvs.x, b_mvs.y, 1, data);
                 case 2 : ReferenceB = data->bRefH + (b_mvs.x-1)/2 + (b_mvs.y/2)*(data->iEdgedWidth); break;  
                 default : ReferenceB = data->bRefHV + (b_mvs.x-1)/2 + ((b_mvs.y-1)/2)*(data->iEdgedWidth); break;  
616          }          }
617    
618          sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
619            sad += (data->lambda16 * d_mv_bits(x, y, zeroMV, 1, 0, 0) * sad)>>10;
620    
621            if (data->chroma) sad += ChromaSAD2((xcf >> 3) + roundtab_76[xcf & 0xf],
622                                                                                    (ycf >> 3) + roundtab_76[ycf & 0xf],
623                                                                                    (xcb >> 3) + roundtab_76[xcb & 0xf],
624                                                                                    (ycb >> 3) + roundtab_76[ycb & 0xf], data);
625    
626          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
627                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
628                  data->currentMV->x = x; data->currentMV->y = y;                  data->currentMV->x = x; data->currentMV->y = y;
629                  *dir = Direction; }                  *dir = Direction;
630            }
631  }  }
632    
633    
634  static void  static void
635  CheckCandidate8(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidateBits16(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
636  {  {
637          int32_t sad;  
638          const uint8_t * Reference;          static int16_t in[64], coeff[64];
639            int32_t bits = 0, sum;
640            VECTOR * current;
641            const uint8_t * ptr;
642            int i, cbp = 0, t, xc, yc;
643    
644          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
645                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
646    
647          switch ( ((x&1)<<1) + (y&1) )          if (!data->qpel_precision) {
648          {                  ptr = GetReference(x, y, data);
649                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;                  current = data->currentMV;
650                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  xc = x; yc = y;
651                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;          } else { // x and y are in 1/4 precision
652                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  ptr = Interpolate16x16qpel(x, y, 0, data);
653                    current = data->currentQMV;
654                    xc = x/2; yc = y/2;
655            }
656    
657            for(i = 0; i < 4; i++) {
658                    int s = 8*((i&1) + (i>>1)*data->iEdgedWidth);
659                    transfer_8to16subro(in, data->Cur + s, ptr + s, data->iEdgedWidth);
660                    fdct(in);
661                    if (data->lambda8 == 0) sum = quant_inter(coeff, in, data->lambda16);
662                    else sum = quant4_inter(coeff, in, data->lambda16);
663                    if (sum > 0) {
664                            cbp |= 1 << (5 - i);
665                            bits += data->temp[i] = CodeCoeffInter_CalcBits(coeff, scan_tables[0]);
666                    } else data->temp[i] = 0;
667            }
668    
669            bits += t = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
670    
671            if (bits < data->iMinSAD[0]) { // there is still a chance, adding chroma
672                    xc = (xc >> 1) + roundtab_79[xc & 0x3];
673                    yc = (yc >> 1) + roundtab_79[yc & 0x3];
674    
675                    //chroma U
676                    ptr = interpolate8x8_switch2(data->RefQ + 64, data->RefCU, 0, 0, xc, yc,  data->iEdgedWidth/2, data->rounding);
677                    transfer_8to16subro(in, ptr, data->CurU, data->iEdgedWidth/2);
678                    fdct(in);
679                    if (data->lambda8 == 0) sum = quant_inter(coeff, in, data->lambda16);
680                    else sum = quant4_inter(coeff, in, data->lambda16);
681                    if (sum > 0) {
682                            cbp |= 1 << (5 - 4);
683                            bits += CodeCoeffInter_CalcBits(coeff, scan_tables[0]);
684                    }
685    
686                    if (bits < data->iMinSAD[0]) {
687                            //chroma V
688                            ptr = interpolate8x8_switch2(data->RefQ + 64, data->RefCV, 0, 0, xc, yc,  data->iEdgedWidth/2, data->rounding);
689                            transfer_8to16subro(in, ptr, data->CurV, data->iEdgedWidth/2);
690                            fdct(in);
691                            if (data->lambda8 == 0) sum = quant_inter(coeff, in, data->lambda16);
692                            else sum = quant4_inter(coeff, in, data->lambda16);
693                            if (sum > 0) {
694                                    cbp |= 1 << (5 - 5);
695                                    bits += CodeCoeffInter_CalcBits(coeff, scan_tables[0]);
696                            }
697                    }
698            }
699    
700            bits += cbpy_tab[15-(cbp>>2)].len;
701            bits += mcbpc_inter_tab[(MODE_INTER & 7) | ((cbp & 3) << 3)].len;
702    
703            if (bits < data->iMinSAD[0]) {
704                    data->iMinSAD[0] = bits;
705                    current[0].x = x; current[0].y = y;
706                    *dir = Direction;
707            }
708    
709            if (data->temp[0] + t < data->iMinSAD[1]) {
710                    data->iMinSAD[1] = data->temp[0] + t; current[1].x = x; current[1].y = y; }
711            if (data->temp[1] < data->iMinSAD[2]) {
712                    data->iMinSAD[2] = data->temp[1]; current[2].x = x; current[2].y = y; }
713            if (data->temp[2] < data->iMinSAD[3]) {
714                    data->iMinSAD[3] = data->temp[2]; current[3].x = x; current[3].y = y; }
715            if (data->temp[3] < data->iMinSAD[4]) {
716                    data->iMinSAD[4] = data->temp[3]; current[4].x = x; current[4].y = y; }
717    
718          }          }
719    static void
720    CheckCandidateBits8(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
721    {
722    
723          sad = sad8(data->Cur, Reference, data->iEdgedWidth);          static int16_t in[64], coeff[64];
724          sad += lambda_vec8[data->iQuant] * d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          int32_t sum, bits;
725            VECTOR * current;
726            const uint8_t * ptr;
727            int cbp;
728    
729          if (sad < *(data->iMinSAD)) {          if ( (x > data->max_dx) || (x < data->min_dx)
730                  *(data->iMinSAD) = sad;                  || (y > data->max_dy) || (y < data->min_dy) ) return;
731                  data->currentMV->x = x; data->currentMV->y = y;  
732                  *dir = Direction; }          if (!data->qpel_precision) {
733                    ptr = GetReference(x, y, data);
734                    current = data->currentMV;
735            } else { // x and y are in 1/4 precision
736                    ptr = Interpolate8x8qpel(x, y, 0, 0, data);
737                    current = data->currentQMV;
738            }
739    
740            transfer_8to16subro(in, data->Cur, ptr, data->iEdgedWidth);
741            fdct(in);
742            if (data->lambda8 == 0) sum = quant_inter(coeff, in, data->lambda16);
743            else sum = quant4_inter(coeff, in, data->lambda16);
744            if (sum > 0) {
745                    bits = CodeCoeffInter_CalcBits(coeff, scan_tables[0]);
746                    cbp = 1;
747            } else cbp = bits = 0;
748    
749            bits += sum = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
750    
751            if (bits < data->iMinSAD[0]) {
752                    data->temp[0] = cbp;
753                    data->iMinSAD[0] = bits;
754                    current[0].x = x; current[0].y = y;
755                    *dir = Direction;
756            }
757  }  }
758    
759  /* CHACK_CANDIATE FUNCTIONS END */  /* CHECK_CANDIATE FUNCTIONS END */
760    
761  /* MAINSEARCH FUNCTIONS START */  /* MAINSEARCH FUNCTIONS START */
762    
# Line 328  Line 768 
768    
769                  int iDirection;                  int iDirection;
770    
771                  do {          for(;;) { //forever
772                          iDirection = 0;                          iDirection = 0;
773                          if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);                          if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);
774                          if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);                          if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);
# Line 337  Line 777 
777    
778                          /* now we're doing diagonal checks near our candidate */                          /* now we're doing diagonal checks near our candidate */
779    
780                          if (iDirection) {               //checking if anything found                  if (iDirection) {               //if anything found
781                                  bDirection = iDirection;                                  bDirection = iDirection;
782                                  iDirection = 0;                                  iDirection = 0;
783                                  x = data->currentMV->x; y = data->currentMV->y;                                  x = data->currentMV->x; y = data->currentMV->y;
# Line 346  Line 786 
786                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);
787                                  } else {                        // what remains here is up or down                                  } else {                        // what remains here is up or down
788                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);
789                                          CHECK_CANDIDATE(x - iDiamondSize, y, 1); }                                  CHECK_CANDIDATE(x - iDiamondSize, y, 1);
790                            }
791    
792                                  if (iDirection) {                                  if (iDirection) {
793                                          bDirection += iDirection;                                          bDirection += iDirection;
794                                          x = data->currentMV->x; y = data->currentMV->y; }                                  x = data->currentMV->x; y = data->currentMV->y;
795                            }
796                          } else {                                //about to quit, eh? not so fast....                          } else {                                //about to quit, eh? not so fast....
797                                  switch (bDirection) {                                  switch (bDirection) {
798                                  case 2:                                  case 2:
# Line 401  Line 843 
843                                  x = data->currentMV->x; y = data->currentMV->y;                                  x = data->currentMV->x; y = data->currentMV->y;
844                          }                          }
845                  }                  }
                 while (1);                              //forever  
846  }  }
847    
848  static void  static void
# Line 451  Line 892 
892                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);
893                                  } else {                        // what remains here is up or down                                  } else {                        // what remains here is up or down
894                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);
895                                          CHECK_CANDIDATE(x - iDiamondSize, y, 1); }                                  CHECK_CANDIDATE(x - iDiamondSize, y, 1);
896                            }
897                                  bDirection += iDirection;                                  bDirection += iDirection;
898                                  x = data->currentMV->x; y = data->currentMV->y;                                  x = data->currentMV->x; y = data->currentMV->y;
899                          }                          }
# Line 462  Line 903 
903    
904  /* MAINSEARCH FUNCTIONS END */  /* MAINSEARCH FUNCTIONS END */
905    
 /* HALFPELREFINE COULD BE A MAINSEARCH FUNCTION, BUT THERE IS NO NEED FOR IT */  
   
906  static void  static void
907  HalfpelRefine(const SearchData * const data)  SubpelRefine(const SearchData * const data)
908  {  {
909  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a half-pel or q-pel refinement */
910            const VECTOR centerMV = data->qpel_precision ? *data->currentQMV : *data->currentMV;
911          VECTOR backupMV = *(data->currentMV);          int iDirection; //only needed because macro expects it
912          int iDirection; //not needed  
913            CHECK_CANDIDATE(centerMV.x, centerMV.y - 1, 0);
914          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);          CHECK_CANDIDATE(centerMV.x + 1, centerMV.y - 1, 0);
915          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);          CHECK_CANDIDATE(centerMV.x + 1, centerMV.y, 0);
916          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);          CHECK_CANDIDATE(centerMV.x + 1, centerMV.y + 1, 0);
917          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y + 1, 0);          CHECK_CANDIDATE(centerMV.x, centerMV.y + 1, 0);
918            CHECK_CANDIDATE(centerMV.x - 1, centerMV.y + 1, 0);
919          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y, 0);          CHECK_CANDIDATE(centerMV.x - 1, centerMV.y, 0);
920          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);  
921  }  }
922    
923  static __inline int  static __inline int
924  SkipDecisionP(const IMAGE * current, const IMAGE * reference,  SkipDecisionP(const IMAGE * current, const IMAGE * reference,
925                                                          const int x, const int y,                                                          const int x, const int y,
926                                                          const uint32_t iEdgedWidth, const uint32_t iQuant)                                                          const uint32_t stride, const uint32_t iQuant, int rrv)
927    
928  {  {
929  /*      keep repeating checks for all b-frames before this P frame,          if(!rrv) {
930          to make sure that SKIP is possible (todo)                  uint32_t sadC = sad8(current->u + x*8 + y*stride*8,
931          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);  
932          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
933          sadC += sad8(current->v + x*8 + y*(iEdgedWidth/2)*8,                  sadC += sad8(current->v + (x + y*stride)*8,
934                                          reference->v + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                                  reference->v + (x + y*stride)*8, stride);
935          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
936                    return 1;
937    
938            } else {
939                    uint32_t sadC = sad16(current->u + x*16 + y*stride*16,
940                                                    reference->u + x*16 + y*stride*16, stride, 256*4096);
941                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP*4) return 0;
942                    sadC += sad16(current->v + (x + y*stride)*16,
943                                                    reference->v + (x + y*stride)*16, stride, 256*4096);
944                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP*4) return 0;
945          return 1;          return 1;
946  }  }
947    }
948    
949  static __inline void  static __inline void
950  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)
951  {  {
952          pMB->mode = MODE_NOT_CODED;          pMB->mode = MODE_NOT_CODED;
953          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = pMB->mv16.x = 0;          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = zeroMV;
954          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = pMB->mv16.y = 0;          pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] = pMB->qmvs[3] = zeroMV;
955          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;
956  }  }
957    
# Line 526  Line 968 
968          const IMAGE *const pCurrent = &current->image;          const IMAGE *const pCurrent = &current->image;
969          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
970    
971          const VECTOR zeroMV = { 0, 0 };          uint32_t mb_width = pParam->mb_width;
972            uint32_t mb_height = pParam->mb_height;
973            const uint32_t iEdgedWidth = pParam->edged_width;
974            const uint32_t MotionFlags = MakeGoodMotionFlags(current->motion_flags, current->global_flags);
975    
976          uint32_t x, y;          uint32_t x, y;
977          uint32_t iIntra = 0;          uint32_t iIntra = 0;
978          int32_t InterBias;          int32_t quant = current->quant, sad00;
979    
980          if (sadInit) (*sadInit) ();          // some pre-initialized thingies for SearchP
981            int32_t temp[8];
982            VECTOR currentMV[5];
983            VECTOR currentQMV[5];
984            int32_t iMinSAD[5];
985            SearchData Data;
986            memset(&Data, 0, sizeof(SearchData));
987            Data.iEdgedWidth = iEdgedWidth;
988            Data.currentMV = currentMV;
989            Data.currentQMV = currentQMV;
990            Data.iMinSAD = iMinSAD;
991            Data.temp = temp;
992            Data.iFcode = current->fcode;
993            Data.rounding = pParam->m_rounding_type;
994            Data.qpel = pParam->m_quarterpel;
995            Data.chroma = MotionFlags & PMV_CHROMA16;
996            Data.rrv = current->global_flags & XVID_REDUCED;
997    
998            if ((current->global_flags & XVID_REDUCED)) {
999                    mb_width = (pParam->width + 31) / 32;
1000                    mb_height = (pParam->height + 31) / 32;
1001                    Data.qpel = 0;
1002            }
1003    
1004          for (y = 0; y < pParam->mb_height; y++) {          Data.RefQ = pRefV->u; // a good place, also used in MC (for similar purpose)
1005                  for (x = 0; x < pParam->mb_width; x++)  {          if (sadInit) (*sadInit) ();
1006    
1007            for (y = 0; y < mb_height; y++) {
1008                    for (x = 0; x < mb_width; x++)  {
1009                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
1010                          int32_t sad00 =  pMB->sad16  
1011                                  = sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,                          if (!Data.rrv) pMB->sad16 =
1012                                                          pRef->y + (x + y * pParam->edged_width) * 16,                                  sad16v(pCurrent->y + (x + y * iEdgedWidth) * 16,
1013                                                            pRef->y + (x + y * iEdgedWidth) * 16,
1014                                                          pParam->edged_width, pMB->sad8 );                                                          pParam->edged_width, pMB->sad8 );
1015    
1016                            else pMB->sad16 =
1017                                    sad32v_c(pCurrent->y + (x + y * iEdgedWidth) * 32,
1018                                                            pRef->y + (x + y * iEdgedWidth) * 32,
1019                                                            pParam->edged_width, pMB->sad8 );
1020    
1021                            if (Data.chroma) {
1022                                    Data.temp[7] = sad8(pCurrent->u + x*8 + y*(iEdgedWidth/2)*8,
1023                                                                            pRef->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2)
1024                                                                    + sad8(pCurrent->v + (x + y*(iEdgedWidth/2))*8,
1025                                                                            pRef->v + (x + y*(iEdgedWidth/2))*8, iEdgedWidth/2);
1026                                    pMB->sad16 += Data.temp[7];
1027                            }
1028    
1029                            sad00 = pMB->sad16;
1030    
1031                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
1032                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
1033                                  pMB->quant = current->quant; }                          } else {
1034                                    if (pMB->dquant != NO_CHANGE) {
1035                                            quant += DQtab[pMB->dquant];
1036                                            if (quant > 31) quant = 31;
1037                                            else if (quant < 1) quant = 1;
1038                                    }
1039                            }
1040                            pMB->quant = current->quant;
1041    
1042  //initial skip decision  //initial skip decision
1043    /* no early skip for GMC (global vector = skip vector is unknown!)  */
1044                          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 */
1045                                  && (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) )
1046                                  if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {                                          if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, iEdgedWidth/2, pMB->quant, Data.rrv)) {
1047                                                  SkipMacroblockP(pMB, sad00);                                                  SkipMacroblockP(pMB, sad00);
1048                                                  continue;                                                  continue;
1049                                  }                                  }
1050                          } else sad00 = 256*4096; // skip not allowed - for final skip decision                          }
1051    
1052                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchP(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
1053                                                  y, current->motion_flags, pMB->quant,                                                  y, MotionFlags, current->global_flags, pMB->quant,
1054                                                  current->fcode, pParam, pMBs, reference->mbs,                                                  &Data, pParam, pMBs, reference->mbs,
1055                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
1056    
1057  /* 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?" */
1058                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)                          if (!(current->global_flags & XVID_GMC))        {
1059                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)                                  if ( pMB->dquant == NO_CHANGE && sad00 < pMB->quant * MAX_SAD00_FOR_SKIP) {
1060                                  { SkipMacroblockP(pMB, sad00); continue; }                                          if (!(current->global_flags & XVID_MODEDECISION_BITS)) {
1061                                                    if ( (100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH * (Data.rrv ? 4:1) )
1062  /* finally, intra decision */                                                          if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, iEdgedWidth/2, pMB->quant, Data.rrv))
1063                                                                    SkipMacroblockP(pMB, sad00);
1064                          InterBias = MV16_INTER_BIAS;                                          } else { // BITS mode decision
1065                          if (pMB->quant > 8)  InterBias += 50 * (pMB->quant - 8); // to make high quants work                                                  if (pMB->sad16 > 10)
1066                          if (y != 0)                                                          SkipMacroblockP(pMB, sad00);  // more than 10 bits would be used for this MB - skip
                                 if ((pMB - pParam->mb_width)->mode == MODE_INTER ) InterBias -= 50;  
                         if (x != 0)  
                                 if ((pMB - 1)->mode == MODE_INTER ) InterBias -= 50;  
   
                         if (InterBias < pMB->sad16)  {  
                                 const int32_t deviation =  
                                         dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,  
                                                   pParam->edged_width);  
1067    
                                 if (deviation < (pMB->sad16 - InterBias)) {  
                                         if (++iIntra >= iLimit) return 1;  
                                         pMB->mode = MODE_INTRA;  
                                         pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =  
                                                 pMB->mvs[3] = zeroMV;  
                                         pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =  
                                                 pMB->sad8[3] = 0;  
1068                                  }                                  }
1069                          }                          }
1070                  }                  }
1071                            if (pMB->mode == MODE_INTRA)
1072                                    if (++iIntra > iLimit) return 1;
1073          }          }
         return 0;  
1074  }  }
1075    
1076            if (current->global_flags & XVID_GMC )  /* GMC only for S(GMC)-VOPs */
1077            {
1078                    current->warp = GlobalMotionEst( pMBs, pParam, current, reference, pRefH, pRefV, pRefHV);
1079            }
1080            return 0;
1081    }
1082    
 #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  
1083    
1084  static __inline int  static __inline int
1085  make_mask(const VECTOR * const pmv, const int i)  make_mask(const VECTOR * const pmv, const int i)
1086  {  {
1087          int mask = 0xFF, j;          int mask = 255, j;
1088          for (j = 0; j < i; j++) {          for (j = 0; j < i; j++) {
1089                  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
1090                  if (pmv[i].x == pmv[j].x) {                  if (pmv[i].x == pmv[j].x) {
1091                          if (pmv[i].y == pmv[j].y + iDiamondSize) { mask &= ~4; continue; }                          if (pmv[i].y == pmv[j].y + iDiamondSize) mask &= ~4;
1092                          if (pmv[i].y == pmv[j].y - iDiamondSize) { mask &= ~8; continue; }                          else if (pmv[i].y == pmv[j].y - iDiamondSize) mask &= ~8;
1093                  } else                  } else
1094                          if (pmv[i].y == pmv[j].y) {                          if (pmv[i].y == pmv[j].y) {
1095                                  if (pmv[i].x == pmv[j].x + iDiamondSize) { mask &= ~1; continue; }                                  if (pmv[i].x == pmv[j].x + iDiamondSize) mask &= ~1;
1096                                  if (pmv[i].x == pmv[j].x - iDiamondSize) { mask &= ~2; continue; }                                  else if (pmv[i].x == pmv[j].x - iDiamondSize) mask &= ~2;
1097                          }                          }
1098          }          }
1099          return mask;          return mask;
1100  }  }
1101    
1102  static __inline void  static __inline void
1103  PreparePredictionsP(VECTOR * const pmv, int x, int y, const int iWcount,  PreparePredictionsP(VECTOR * const pmv, int x, int y, int iWcount,
1104                          const int iHcount, const MACROBLOCK * const prevMB)                          int iHcount, const MACROBLOCK * const prevMB, int rrv)
1105  {  {
1106    
1107  //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
1108            if (rrv) { iWcount /= 2; iHcount /= 2; }
1109    
1110          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour          if ( (y != 0) && (x < (iWcount-1)) ) {          // [5] top-right neighbour
1111                  pmv[5].x = EVEN(pmv[3].x);                  pmv[5].x = EVEN(pmv[3].x);
1112                  pmv[5].y = EVEN(pmv[3].y); }                  pmv[5].y = EVEN(pmv[3].y);
1113          else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
1114    
1115          if (x != 0) { pmv[3].x = EVEN(pmv[1].x); pmv[3].y = EVEN(pmv[1].y); }// pmv[3] is left neighbour          if (x != 0) { pmv[3].x = EVEN(pmv[1].x); pmv[3].y = EVEN(pmv[1].y); }// pmv[3] is left neighbour
1116          else pmv[3].x = pmv[3].y = 0;          else pmv[3].x = pmv[3].y = 0;
# Line 642  Line 1126 
1126          pmv[2].x = EVEN(prevMB->mvs[0].x); // [2] is last frame          pmv[2].x = EVEN(prevMB->mvs[0].x); // [2] is last frame
1127          pmv[2].y = EVEN(prevMB->mvs[0].y);          pmv[2].y = EVEN(prevMB->mvs[0].y);
1128    
1129          if ((x != iWcount-1) && (y != iHcount-1)) {          if ((x < iWcount-1) && (y < iHcount-1)) {
1130                  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
1131                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y); }                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
1132          else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
1133    
1134            if (rrv) {
1135                    int i;
1136                    for (i = 0; i < 7; i++) {
1137                            pmv[i].x = RRV_MV_SCALEUP(pmv[i].x);
1138                            pmv[i].y = RRV_MV_SCALEUP(pmv[i].y);
1139                    }
1140            }
1141  }  }
1142    
1143  static void  static int
1144  SearchP(const uint8_t * const pRef,  ModeDecision(const uint32_t iQuant, SearchData * const Data,
                 const uint8_t * const pRefH,  
                 const uint8_t * const pRefV,  
                 const uint8_t * const pRefHV,  
                 const IMAGE * const pCur,  
                 const int x,  
                 const int y,  
                 const uint32_t MotionFlags,  
                 const uint32_t iQuant,  
                 const uint32_t iFcode,  
                 const MBParam * const pParam,  
                 const MACROBLOCK * const pMBs,  
                 const MACROBLOCK * const prevMBs,  
1145                  int inter4v,                  int inter4v,
1146                  MACROBLOCK * const pMB)                  MACROBLOCK * const pMB,
1147  {                  const MACROBLOCK * const pMBs,
1148                    const int x, const int y,
1149          const int32_t iEdgedWidth = pParam->edged_width;                  const MBParam * const pParam,
1150                    const uint32_t MotionFlags,
1151          int i, iDirection = 255, mask, threshA;                  const uint32_t GlobalFlags)
1152          int32_t temp[5];  {
         VECTOR currentMV[5], pmv[7];  
         int32_t psad[4], iMinSAD[5];  
         MainSearchFunc * MainSearchPtr;  
         SearchData Data;  
1153    
1154          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, psad);  //has to be changed to get_pmv(2)()          int mode = MODE_INTER;
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,  
                                 pParam->width, pParam->height, iFcode);  
1155    
1156          Data.predMV = pmv[0];          if (!(GlobalFlags & XVID_MODEDECISION_BITS)) { //normal, fast, SAD-based mode decision
1157          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;                  int intra = 0;
1158          Data.iEdgedWidth = iEdgedWidth;                  int sad;
1159          Data.currentMV = currentMV;                  int InterBias = MV16_INTER_BIAS;
1160          Data.iMinSAD = iMinSAD;                  if (inter4v == 0 || Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
1161          Data.Ref = pRef + (x + iEdgedWidth*y)*16;                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant) {
1162          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;                                  mode = 0; //inter
1163          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;                                  sad = Data->iMinSAD[0];
1164          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;                  } else {
1165          Data.temp = temp;                          mode = MODE_INTER4V;
1166                            sad = Data->iMinSAD[1] + Data->iMinSAD[2] +
1167                                                    Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant;
1168                            Data->iMinSAD[0] = sad;
1169                    }
1170    
1171                    /* intra decision */
1172    
1173                    if (iQuant > 8) InterBias += 100 * (iQuant - 8); // to make high quants work
1174                    if (y != 0)
1175                            if ((pMB - pParam->mb_width)->mode == MODE_INTRA ) InterBias -= 80;
1176                    if (x != 0)
1177                            if ((pMB - 1)->mode == MODE_INTRA ) InterBias -= 80;
1178    
1179                    if (Data->chroma) InterBias += 50; // to compensate bigger SAD
1180                    if (Data->rrv) InterBias *= 4;
1181    
1182                    if (InterBias < pMB->sad16) {
1183                            int32_t deviation;
1184                            if (!Data->rrv) deviation = dev16(Data->Cur, Data->iEdgedWidth);
1185                            else deviation = dev16(Data->Cur, Data->iEdgedWidth) +
1186                                    dev16(Data->Cur+8, Data->iEdgedWidth) +
1187                                    dev16(Data->Cur + 8*Data->iEdgedWidth, Data->iEdgedWidth) +
1188                                    dev16(Data->Cur+8+8*Data->iEdgedWidth, Data->iEdgedWidth);
1189    
1190                            if (deviation < (sad - InterBias))  return MODE_INTRA;// intra
1191                    }
1192                    return mode;
1193    
1194            } else {
1195    
1196                    int bits, intra, i;
1197                    VECTOR backup[5], *v;
1198                    Data->lambda16 = iQuant;
1199                    Data->lambda8 = pParam->m_quant_type;
1200    
1201                    v = Data->qpel ? Data->currentQMV : Data->currentMV;
1202                    for (i = 0; i < 5; i++) {
1203                            Data->iMinSAD[i] = 256*4096;
1204                            backup[i] = v[i];
1205                    }
1206    
1207                    bits = CountMBBitsInter(Data, pMBs, x, y, pParam, MotionFlags);
1208                    if (bits == 0) return MODE_INTER; // quick stop
1209    
1210                    if (inter4v) {
1211                            int inter4v = CountMBBitsInter4v(Data, pMB, pMBs, x, y, pParam, MotionFlags, backup);
1212                            if (inter4v < bits) { Data->iMinSAD[0] = bits = inter4v; mode = MODE_INTER4V; }
1213                    }
1214    
1215    
1216                    intra = CountMBBitsIntra(Data);
1217    
1218                    if (intra < bits) { *Data->iMinSAD = bits = intra; return MODE_INTRA; }
1219    
1220                    return mode;
1221            }
1222    }
1223    
1224    static void
1225    SearchP(const IMAGE * const pRef,
1226                    const uint8_t * const pRefH,
1227                    const uint8_t * const pRefV,
1228                    const uint8_t * const pRefHV,
1229                    const IMAGE * const pCur,
1230                    const int x,
1231                    const int y,
1232                    const uint32_t MotionFlags,
1233                    const uint32_t GlobalFlags,
1234                    const uint32_t iQuant,
1235                    SearchData * const Data,
1236                    const MBParam * const pParam,
1237                    const MACROBLOCK * const pMBs,
1238                    const MACROBLOCK * const prevMBs,
1239                    int inter4v,
1240                    MACROBLOCK * const pMB)
1241    {
1242    
1243            int i, iDirection = 255, mask, threshA;
1244            VECTOR pmv[7];
1245    
1246            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1247                                                    pParam->width, pParam->height, Data->iFcode - Data->qpel, 0, Data->rrv);
1248    
1249          Data.iQuant = iQuant;          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);
         Data.iFcode = iFcode;  
1250    
1251          if (!(MotionFlags & PMV_HALFPEL16)) {          Data->temp[5] = Data->temp[6] = 0; // chroma-sad cache
1252                  Data.min_dx = EVEN(Data.min_dx);          i = Data->rrv ? 2 : 1;
1253                  Data.max_dx = EVEN(Data.max_dx);          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16*i;
1254                  Data.min_dy = EVEN(Data.min_dy);          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
1255                  Data.max_dy = EVEN(Data.max_dy); }          Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
1256    
1257          for(i = 0;  i < 5; i++) currentMV[i].x = currentMV[i].y = 0;          Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16*i;
1258            Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16*i;
1259          i = d_mv_bits(pmv[0].x, pmv[0].y, iFcode);          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16*i;
1260            Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16*i;
1261          iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;          Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
1262          iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;          Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
1263          iMinSAD[2] = pMB->sad8[1];  
1264          iMinSAD[3] = pMB->sad8[2];          Data->lambda16 = lambda_vec16[iQuant];
1265          iMinSAD[4] = pMB->sad8[3];          Data->lambda8 = lambda_vec8[iQuant];
1266            Data->qpel_precision = 0;
1267    
1268          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
1269    
1270          if ((x == 0) && (y == 0)) threshA = 512;          for(i = 0; i < 5; i++)
1271          else {                  Data->currentMV[i].x = Data->currentMV[i].y = 0;
1272                  threshA = psad[0] + 20;  
1273            if (Data->qpel) Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1274            else Data->predMV = pmv[0];
1275    
1276            i = d_mv_bits(0, 0, Data->predMV, Data->iFcode, 0, 0);
1277            Data->iMinSAD[0] = pMB->sad16 + ((Data->lambda16 * i * pMB->sad16)>>10);
1278            Data->iMinSAD[1] = pMB->sad8[0] + ((Data->lambda8 * i * (pMB->sad8[0]+NEIGH_8X8_BIAS)) >> 10);
1279            Data->iMinSAD[2] = pMB->sad8[1];
1280            Data->iMinSAD[3] = pMB->sad8[2];
1281            Data->iMinSAD[4] = pMB->sad8[3];
1282    
1283            if ((!(GlobalFlags & XVID_MODEDECISION_BITS)) || (x | y)) {
1284                    threshA = Data->temp[0]; // that's where we keep this SAD atm
1285                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
1286                  if (threshA > 1024) threshA = 1024; }                  else if (threshA > 1024) threshA = 1024;
1287            } else
1288                    threshA = 512;
1289    
1290          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,
1291                                          prevMBs + x + y * pParam->mb_width);                                          prevMBs + x + y * pParam->mb_width, Data->rrv);
1292    
1293          if (inter4v) CheckCandidate = CheckCandidate16;          if (!Data->rrv) {
1294          else CheckCandidate = CheckCandidate16no4v;                  if (inter4v | Data->chroma) CheckCandidate = CheckCandidate16;
1295                            else CheckCandidate = CheckCandidate16no4v; //for extra speed
1296            } else CheckCandidate = CheckCandidate32;
1297    
1298  /* main loop. checking all predictions */  /* main loop. checking all predictions (but first, which is 0,0 and has been checked in MotionEstimation())*/
1299    
1300          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
1301                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1302                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1303                  if (iMinSAD[0] < threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1304          }          }
1305    
1306          if ((iMinSAD[0] <= threshA) ||          if ((Data->iMinSAD[0] <= threshA) ||
1307                          (MVequal(currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
1308                          (iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {                          (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {
1309                  inter4v = 0;                  if (!(GlobalFlags & XVID_MODEDECISION_BITS)) inter4v = 0;       }
1310                  if (MotionFlags & PMV_QUICKSTOP16) goto PMVfast16_Terminate_without_Refine;          else {
                 if (MotionFlags & PMV_EARLYSTOP16) {  
                         CheckCandidate = CheckCandidate16no4v; // I sure hope it's faster  
                         goto PMVfast16_Terminate_with_Refine;  
                 }  
         }  
1311    
1312          if (MotionFlags & PMV_USESQUARES16)                  MainSearchFunc * MainSearchPtr;
1313                  MainSearchPtr = SquareSearch;                  if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
1314          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
                 MainSearchPtr = AdvDiamondSearch;  
1315                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1316    
1317          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, iDirection);                  MainSearchPtr(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1318    
1319  /* extended search, diamond starting in 0,0 and in prediction.  /* extended search, diamond starting in 0,0 and in prediction.
1320          note that this search is/might be done in halfpel positions,          note that this search is/might be done in halfpel positions,
# Line 756  Line 1322 
1322    
1323          if (MotionFlags & PMV_EXTSEARCH16) {          if (MotionFlags & PMV_EXTSEARCH16) {
1324                  int32_t bSAD;                  int32_t bSAD;
1325                  VECTOR startMV = Data.predMV, backupMV = currentMV[0];                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
1326                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?                          if (Data->rrv) {
1327                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);                                  startMV.x = RRV_MV_SCALEUP(startMV.x);
1328                                    startMV.y = RRV_MV_SCALEUP(startMV.y);
1329                            }
1330                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1331                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1332    
1333                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  CheckCandidate(startMV.x, startMV.y, 255, &iDirection, Data);
1334                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  MainSearchPtr(startMV.x, startMV.y, Data, 255);
1335                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1336                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1337                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1338                  }                  }
1339    
1340                  backupMV = currentMV[0];                          backupMV = Data->currentMV[0];
1341                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;                          startMV.x = startMV.y = 1;
                 else startMV.x = startMV.y = 0;  
1342                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1343                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1344    
1345                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  CheckCandidate(startMV.x, startMV.y, 255, &iDirection, Data);
1346                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  MainSearchPtr(startMV.x, startMV.y, Data, 255);
1347                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1348                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1349                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1350                            }
1351                  }                  }
1352          }          }
1353    
1354  PMVfast16_Terminate_with_Refine:          if (MotionFlags & PMV_HALFPELREFINE16)
1355                    if ((!(MotionFlags & HALFPELREFINE16_BITS)) || Data->iMinSAD[0] < 200*(int)iQuant)
1356                            SubpelRefine(Data);
1357    
1358            for(i = 0; i < 5; i++) {
1359                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1360                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1361            }
1362    
1363          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (MotionFlags & PMV_QUARTERPELREFINE16)
1364                    if ((!(MotionFlags & QUARTERPELREFINE16_BITS)) || (Data->iMinSAD[0] < 200*(int)iQuant)) {
1365                            Data->qpel_precision = 1;
1366                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1367                                            pParam->width, pParam->height, Data->iFcode, 1, 0);
1368    
1369  PMVfast16_Terminate_without_Refine:                          SubpelRefine(Data);
1370                    }
1371    
1372          if (inter4v)          if ((!(GlobalFlags & XVID_MODEDECISION_BITS)) && (Data->iMinSAD[0] < (int32_t)iQuant * 30)) inter4v = 0;
                 for(i = 0; i < 4; i++)  
                         Search8(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);  
1373    
1374          if (!(inter4v) ||          if (inter4v && (!(GlobalFlags & XVID_MODEDECISION_BITS) ||
1375                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                          (!(MotionFlags & QUARTERPELREFINE8_BITS)) || (!(MotionFlags & HALFPELREFINE8_BITS)) ||
1376  // INTER MODE                          ((!(MotionFlags & EXTSEARCH_BITS)) && (!(MotionFlags&PMV_EXTSEARCH8)) ))) {
1377                  pMB->mode = MODE_INTER;                  // if decision is BITS-based and all refinement steps will be done in BITS domain, there is no reason to call this loop
                 pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]  
                         = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];  
1378    
1379                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  SearchData Data8;
1380                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                  memcpy(&Data8, Data, sizeof(SearchData)); //quick copy of common data
1381    
1382                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1383                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                  Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1384                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1385                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1386    
1387                    if ((Data->chroma) && (!(GlobalFlags & XVID_MODEDECISION_BITS))) {
1388                            // chroma is only used for comparsion to INTER. if the comparsion will be done in BITS domain, there is no reason to compute it
1389                            int sumx = 0, sumy = 0;
1390                            const int div = 1 + Data->qpel;
1391                            const VECTOR * const mv = Data->qpel ? pMB->qmvs : pMB->mvs;
1392    
1393                            for (i = 0; i < 4; i++) {
1394                                    sumx += mv[i].x / div;
1395                                    sumy += mv[i].y / div;
1396                            }
1397    
1398                            Data->iMinSAD[1] += ChromaSAD(  (sumx >> 3) + roundtab_76[sumx & 0xf],
1399                                                                                            (sumy >> 3) + roundtab_76[sumy & 0xf], Data);
1400                    }
1401            }
1402    
1403            inter4v = ModeDecision(iQuant, Data, inter4v, pMB, pMBs, x, y, pParam, MotionFlags, GlobalFlags);
1404    
1405            if (Data->rrv) {
1406                            Data->currentMV[0].x = RRV_MV_SCALEDOWN(Data->currentMV[0].x);
1407                            Data->currentMV[0].y = RRV_MV_SCALEDOWN(Data->currentMV[0].y);
1408            }
1409    
1410            if (inter4v == MODE_INTER) {
1411                    pMB->mode = MODE_INTER;
1412                    pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1413                    pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = Data->iMinSAD[0];
1414    
1415                    if(Data->qpel) {
1416                            pMB->qmvs[0] = pMB->qmvs[1]
1417                                    = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1418                            pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predMV.x;
1419                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predMV.y;
1420          } else {          } else {
1421  // INTER4V MODE; all other things are already set in Search8                          pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1422                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1423                    }
1424    
1425            } else if (inter4v == MODE_INTER4V) {
1426                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1427                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[0];
1428            } else { // INTRA mode
1429                    SkipMacroblockP(pMB, 0); // not skip, but similar enough
1430                    pMB->mode = MODE_INTRA;
1431          }          }
1432    
1433  }  }
# Line 820  Line 1439 
1439                  const MBParam * const pParam,                  const MBParam * const pParam,
1440                  MACROBLOCK * const pMB,                  MACROBLOCK * const pMB,
1441                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
1442                  const int block)                  const int block,
1443                    SearchData * const Data)
1444  {  {
1445          SearchData Data;          int i = 0;
1446            Data->iMinSAD = OldData->iMinSAD + 1 + block;
1447            Data->currentMV = OldData->currentMV + 1 + block;
1448            Data->currentQMV = OldData->currentQMV + 1 + block;
1449    
1450            if(Data->qpel) {
1451                    Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2, y/2, block);
1452                    if (block != 0) i = d_mv_bits(  Data->currentQMV->x, Data->currentQMV->y,
1453                                                                                    Data->predMV, Data->iFcode, 0, 0);
1454            } else {
1455                    Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2, y/2, block);
1456                    if (block != 0) i = d_mv_bits(  Data->currentMV->x, Data->currentMV->y,
1457                                                                                    Data->predMV, Data->iFcode, 0, Data->rrv);
1458            }
1459    
1460          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          *(Data->iMinSAD) += (Data->lambda8 * i * (*Data->iMinSAD + NEIGH_8X8_BIAS))>>10;
         Data.iMinSAD = OldData->iMinSAD + 1 + block;  
         Data.currentMV = OldData->currentMV+1+block;  
         Data.iFcode = OldData->iFcode;  
         Data.iQuant = OldData->iQuant;  
   
         if (block != 0)  
                 *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *  
                                                                 d_mv_bits(      Data.currentMV->x - Data.predMV.x,  
                                                                                         Data.currentMV->y - Data.predMV.y,  
                                                                                         Data.iFcode);  
   
   
         if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {  
   
                 Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));  
                 Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));  
                 Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));  
                 Data.RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));  
1461    
1462                  Data.iEdgedWidth = pParam->edged_width;          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8|PMV_QUARTERPELREFINE8)) {
1463                    if (Data->rrv) i = 2; else i = 1;
1464    
1465                    Data->Ref = OldData->Ref + i * 8 * ((block&1) + Data->iEdgedWidth*(block>>1));
1466                    Data->RefH = OldData->RefH + i * 8 * ((block&1) + Data->iEdgedWidth*(block>>1));
1467                    Data->RefV = OldData->RefV + i * 8 * ((block&1) + Data->iEdgedWidth*(block>>1));
1468                    Data->RefHV = OldData->RefHV + i * 8 * ((block&1) + Data->iEdgedWidth*(block>>1));
1469    
1470                  Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Cur = OldData->Cur + i * 8 * ((block&1) + Data->iEdgedWidth*(block>>1));
1471                    Data->qpel_precision = 0;
1472    
1473                  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,
1474                                  pParam->width, pParam->height, OldData->iFcode);                                          pParam->width, pParam->height, Data->iFcode - Data->qpel, 0, Data->rrv);
1475    
1476                  CheckCandidate = CheckCandidate8;                  if (!Data->rrv) CheckCandidate = CheckCandidate8;
1477                    else CheckCandidate = CheckCandidate16no4v;
1478    
1479                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & PMV_EXTSEARCH8 && (!(MotionFlags & EXTSEARCH_BITS))) {
1480                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1481    
1482                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1483                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1484                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1485                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1486    
1487                          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);     }                          MainSearchPtr(Data->currentMV->x, Data->currentMV->y, Data, 255);
1488    
1489                            if(*(Data->iMinSAD) < temp_sad) {
1490                                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1491                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1492                            }
1493                    }
1494    
1495                    if (MotionFlags & PMV_HALFPELREFINE8) {
1496                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1497    
1498                            SubpelRefine(Data); // perform halfpel refine of current best vector
1499    
1500                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                          if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1501                                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1502                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1503                            }
1504          }          }
1505    
1506          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;                  if (Data->qpel && MotionFlags & PMV_QUARTERPELREFINE8) {
1507          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;                                  Data->qpel_precision = 1;
1508          pMB->mvs[block] = *(Data.currentMV);                                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1509          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                                          pParam->width, pParam->height, Data->iFcode, 1, 0);
1510                                    SubpelRefine(Data);
1511                    }
1512  }  }
1513    
1514  /* B-frames code starts here */          if (Data->rrv) {
1515                            Data->currentMV->x = RRV_MV_SCALEDOWN(Data->currentMV->x);
1516                            Data->currentMV->y = RRV_MV_SCALEDOWN(Data->currentMV->y);
1517            }
1518    
1519            if(Data->qpel) {
1520                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predMV.x;
1521                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predMV.y;
1522                    pMB->qmvs[block] = *Data->currentQMV;
1523            } else {
1524                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1525                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1526            }
1527    
1528            pMB->mvs[block] = *Data->currentMV;
1529            pMB->sad8[block] = 4 * *Data->iMinSAD;
1530    }
1531    
1532    /* motion estimation for B-frames */
1533    
1534  static __inline VECTOR  static __inline VECTOR
1535  ChoosePred(const MACROBLOCK * const pMB, const uint32_t mode)  ChoosePred(const MACROBLOCK * const pMB, const uint32_t mode)
1536  {  {
1537  /* the stupidiest function ever */  /* the stupidiest function ever */
1538          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];  
1539  }  }
1540    
1541  static void __inline  static void __inline
# Line 896  Line 1553 
1553          pmv[2] = ChoosePred(pMB, mode_curr);          pmv[2] = ChoosePred(pMB, mode_curr);
1554          pmv[2].x = EVEN(pmv[2].x); pmv[2].y = EVEN(pmv[2].y);          pmv[2].x = EVEN(pmv[2].x); pmv[2].y = EVEN(pmv[2].y);
1555    
         pmv[3].x = pmv[3].y = 0;  
1556          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour
1557                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);
1558                  pmv[3].x = EVEN(pmv[3].x); pmv[3].y = EVEN(pmv[3].y); }                  pmv[3].x = EVEN(pmv[3].x); pmv[3].y = EVEN(pmv[3].y);
1559            } else pmv[3].x = pmv[3].y = 0;
1560    
1561          if (y != 0) {          if (y != 0) {
1562                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);
# Line 911  Line 1568 
1568                  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);
1569          } else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
1570    
1571          if ((x != 0)&&(y != 0)) {          if (x != 0 && y != 0) {
1572                  pmv[6] = ChoosePred(pMB-1-iWcount, mode_curr);                  pmv[6] = ChoosePred(pMB-1-iWcount, mode_curr);
1573                  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);
1574          } else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
   
 // more?  
1575  }  }
1576    
1577    
1578  /* search backward or forward, for b-frames */  /* search backward or forward */
1579  static void  static void
1580  SearchBF(       const uint8_t * const pRef,  SearchBF(       const IMAGE * const pRef,
1581                          const uint8_t * const pRefH,                          const uint8_t * const pRefH,
1582                          const uint8_t * const pRefV,                          const uint8_t * const pRefV,
1583                          const uint8_t * const pRefHV,                          const uint8_t * const pRefHV,
1584                          const IMAGE * const pCur,                          const IMAGE * const pCur,
1585                          const int x, const int y,                          const int x, const int y,
1586                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
1587                          const uint32_t iFcode,                          const uint32_t iFcode,
1588                          const MBParam * const pParam,                          const MBParam * const pParam,
1589                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
1590                          const VECTOR * const predMV,                          const VECTOR * const predMV,
1591                          int32_t * const best_sad,                          int32_t * const best_sad,
1592                          const int32_t mode_current)                          const int32_t mode_current,
1593                            SearchData * const Data)
1594  {  {
1595    
1596          const int32_t iEdgedWidth = pParam->edged_width;          int i, iDirection = 255, mask;
1597            VECTOR pmv[7];
         int i, iDirection, mask;  
         VECTOR currentMV, pmv[7];  
1598          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1599          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
1600          SearchData Data;          Data->iFcode = iFcode;
1601            Data->qpel_precision = 0;
1602            Data->temp[5] = Data->temp[6] = Data->temp[7] = 256*4096; // reset chroma-sad cache
1603    
1604          Data.iMinSAD = &iMinSAD;          Data->Ref = pRef->y + (x + y * Data->iEdgedWidth) * 16;
1605          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->RefH = pRefH + (x + y * Data->iEdgedWidth) * 16;
1606          Data.iEdgedWidth = iEdgedWidth;          Data->RefV = pRefV + (x + y * Data->iEdgedWidth) * 16;
1607          Data.currentMV = &currentMV;          Data->RefHV = pRefHV + (x + y * Data->iEdgedWidth) * 16;
1608          Data.iMinSAD = &iMinSAD;          Data->RefCU = pRef->u + (x + y * Data->iEdgedWidth/2) * 8;
1609          Data.Ref = pRef + (x + y * iEdgedWidth) * 16;          Data->RefCV = pRef->v + (x + y * Data->iEdgedWidth/2) * 8;
1610          Data.RefH = pRefH + (x + y * iEdgedWidth) * 16;  
1611          Data.RefV = pRefV + (x + y * iEdgedWidth) * 16;          Data->predMV = *predMV;
         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);  
1612    
1613          currentMV.x = currentMV.y = 0;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1614                                    pParam->width, pParam->height, iFcode - Data->qpel, 0, 0);
1615    
1616            pmv[0] = Data->predMV;
1617            if (Data->qpel) { pmv[0].x /= 2; pmv[0].y /= 2; }
1618    
1619            PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
1620    
1621            Data->currentMV->x = Data->currentMV->y = 0;
1622          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1623    
1624  // main loop. checking all predictions  // main loop. checking all predictions
1625          for (i = 0; i < 8; i++) {          for (i = 0; i < 7; i++) {
1626                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1627                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1628          }          }
1629    
1630          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
1631                  MainSearchPtr = SquareSearch;          else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
         else if (MotionFlags & PMV_ADVANCEDDIAMOND16)  
                 MainSearchPtr = AdvDiamondSearch;  
1632                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1633    
1634          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          MainSearchPtr(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1635    
1636            SubpelRefine(Data);
1637    
1638          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (Data->qpel && *Data->iMinSAD < *best_sad + 300) {
1639                    Data->currentQMV->x = 2*Data->currentMV->x;
1640                    Data->currentQMV->y = 2*Data->currentMV->y;
1641                    Data->qpel_precision = 1;
1642                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1643                                            pParam->width, pParam->height, iFcode, 1, 0);
1644                    SubpelRefine(Data);
1645            }
1646    
1647  // 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];  
1648    
1649            if (mode_current == MODE_FORWARD) *Data->iMinSAD += 4 * Data->lambda16;
1650            else *Data->iMinSAD += 3 * Data->lambda16;
1651    
1652          if (iMinSAD < *best_sad) {          if (*Data->iMinSAD < *best_sad) {
1653                  *best_sad = iMinSAD;                  *best_sad = *Data->iMinSAD;
1654                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1655                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  if (Data->qpel) {
1656                  pMB->pmvs[0].y = currentMV.y - predMV->y;                          pMB->pmvs[0].x = Data->currentQMV->x - predMV->x;
1657                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                          pMB->pmvs[0].y = Data->currentQMV->y - predMV->y;
1658                  else pMB->b_mvs[0] = currentMV;                          if (mode_current == MODE_FORWARD)
1659                                    pMB->qmvs[0] = *Data->currentQMV;
1660                            else
1661                                    pMB->b_qmvs[0] = *Data->currentQMV;
1662                    } else {
1663                            pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1664                            pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1665                    }
1666                    if (mode_current == MODE_FORWARD) pMB->mvs[0] = *Data->currentMV;
1667                    else pMB->b_mvs[0] = *Data->currentMV;
1668          }          }
1669    
1670            if (mode_current == MODE_FORWARD) *(Data->currentMV+2) = *Data->currentMV;
1671            else *(Data->currentMV+1) = *Data->currentMV; //we store currmv for interpolate search
1672  }  }
1673    
1674  static int32_t  static void
1675  SearchDirect(const uint8_t * const f_Ref,  SkipDecisionB(const IMAGE * const pCur,
1676                                    const IMAGE * const f_Ref,
1677                                    const IMAGE * const b_Ref,
1678                                    MACROBLOCK * const pMB,
1679                                    const uint32_t x, const uint32_t y,
1680                                    const SearchData * const Data)
1681    {
1682            int dx = 0, dy = 0, b_dx = 0, b_dy = 0;
1683            int32_t sum;
1684            const int div = 1 + Data->qpel;
1685            int k;
1686            const uint32_t stride = Data->iEdgedWidth/2;
1687    //this is not full chroma compensation, only it's fullpel approximation. should work though
1688    
1689            for (k = 0; k < 4; k++) {
1690                    dy += Data->directmvF[k].y / div;
1691                    dx += Data->directmvF[0].x / div;
1692                    b_dy += Data->directmvB[0].y / div;
1693                    b_dx += Data->directmvB[0].x / div;
1694            }
1695    
1696            dy = (dy >> 3) + roundtab_76[dy & 0xf];
1697            dx = (dx >> 3) + roundtab_76[dx & 0xf];
1698            b_dy = (b_dy >> 3) + roundtab_76[b_dy & 0xf];
1699            b_dx = (b_dx >> 3) + roundtab_76[b_dx & 0xf];
1700    
1701            sum = sad8bi(pCur->u + 8 * x + 8 * y * stride,
1702                                            f_Ref->u + (y*8 + dy/2) * stride + x*8 + dx/2,
1703                                            b_Ref->u + (y*8 + b_dy/2) * stride + x*8 + b_dx/2,
1704                                            stride);
1705    
1706            if (sum >= 2 * MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) return; //no skip
1707    
1708            sum += sad8bi(pCur->v + 8*x + 8 * y * stride,
1709                                            f_Ref->v + (y*8 + dy/2) * stride + x*8 + dx/2,
1710                                            b_Ref->v + (y*8 + b_dy/2) * stride + x*8 + b_dx/2,
1711                                            stride);
1712    
1713            if (sum < 2 * MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) pMB->mode = MODE_DIRECT_NONE_MV; //skipped
1714    }
1715    
1716    static __inline uint32_t
1717    SearchDirect(const IMAGE * const f_Ref,
1718                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1719                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
1720                                  const uint8_t * const f_RefHV,                                  const uint8_t * const f_RefHV,
1721                                  const uint8_t * const b_Ref,                                  const IMAGE * const b_Ref,
1722                                  const uint8_t * const b_RefH,                                  const uint8_t * const b_RefH,
1723                                  const uint8_t * const b_RefV,                                  const uint8_t * const b_RefV,
1724                                  const uint8_t * const b_RefHV,                                  const uint8_t * const b_RefHV,
1725                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1726                                  const int x, const int y,                                  const int x, const int y,
1727                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1728                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1729                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1730                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1731                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1732                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1733                                    SearchData * const Data)
1734    
1735  {  {
1736          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
1737          int32_t iMinSAD = 0, skip_sad;          int k = (x + Data->iEdgedWidth*y) * 16;
         int k;  
         VECTOR currentMV;  
1738          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
         SearchData Data;  
1739    
1740          Data.iMinSAD = &iMinSAD;          *Data->iMinSAD = 256*4096;
1741          Data.Cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;          Data->Ref = f_Ref->y + k;
1742          Data.iEdgedWidth = iEdgedWidth;          Data->RefH = f_RefH + k;
1743          Data.currentMV = &currentMV;          Data->RefV = f_RefV + k;
1744          Data.iQuant = iQuant;          Data->RefHV = f_RefHV + k;
1745          Data.referencemv = b_mb->mvs;          Data->bRef = b_Ref->y + k;
1746            Data->bRefH = b_RefH + k;
1747          Data.Ref= f_Ref + (x + iEdgedWidth*y) * 16;          Data->bRefV = b_RefV + k;
1748          Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;          Data->bRefHV = b_RefHV + k;
1749          Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;          Data->RefCU = f_Ref->u + (x + (Data->iEdgedWidth/2) * y) * 8;
1750          Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;          Data->RefCV = f_Ref->v + (x + (Data->iEdgedWidth/2) * y) * 8;
1751          Data.bRef = b_Ref + (x + iEdgedWidth*y) * 16;          Data->b_RefCU = b_Ref->u + (x + (Data->iEdgedWidth/2) * y) * 8;
1752          Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;          Data->b_RefCV = b_Ref->v + (x + (Data->iEdgedWidth/2) * y) * 8;
1753          Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;  
1754          Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;          k = Data->qpel ? 4 : 2;
1755  /*          Data->max_dx = k * (pParam->width - x * 16);
1756  //What we do here is a complicated version of CheckCandidateDirect(0,0);          Data->max_dy = k * (pParam->height - y * 16);
1757  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);
1758            Data->min_dy = -k * (16 + y * 16);
1759    
1760  */          Data->referencemv = Data->qpel ? b_mb->qmvs : b_mb->mvs;
1761          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);  
1762    
1763          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1764                  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);
1765                  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;
1766                  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);
1767                  pMB->b_mvs[k].y = Data.directmvB[k].y = ((TRB - TRD) * Data.referencemv[k].y) / TRD;                  pMB->b_mvs[k].y = Data->directmvB[k].y = ((TRB - TRD) * Data->referencemv[k].y) / TRD;
   
         if (( pMB->mvs[k].x > Data.max_dx ) || ( pMB->mvs[k].x < Data.min_dx )  
                         || ( pMB->mvs[k].y > Data.max_dy ) || ( pMB->mvs[k].y < Data.min_dy )  
                         || ( pMB->b_mvs[k].x > Data.max_dx ) || ( pMB->b_mvs[k].x < Data.min_dx )  
                         || ( pMB->b_mvs[k].y > Data.max_dy ) || ( pMB->b_mvs[k].y < Data.min_dy )) {  
 /*  
                 fprintf(debug, "\nERROR - out of range : vector %d,%d and %d,%d\n", pMB->mvs[k].x, pMB->mvs[k].y,pMB->b_mvs[k].x,pMB->b_mvs[k].y );  
                 fprintf(debug, " range is x: %d..%d y: %d..%d \n", Data.min_dx,Data.max_dx,Data.min_dy,Data.max_dy);  
                 fprintf(debug,"macroblock %d, %d \n", x, y);  
                 fprintf(debug, "direct MV is %d,%d \n", directmv[k].x, directmv[k].y);  
 */  
                 *best_sad = 256*4096; // in that case, we won't use direct mode  
                 pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"  
                 pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;  /* because backwards and interpol might rely on this */  
                 return 0; }  
1768    
1769                    if ( (pMB->b_mvs[k].x > Data->max_dx) | (pMB->b_mvs[k].x < Data->min_dx)
1770                            | (pMB->b_mvs[k].y > Data->max_dy) | (pMB->b_mvs[k].y < Data->min_dy) ) {
1771    
1772                            *best_sad = 256*4096; // in that case, we won't use direct mode
1773                            pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
1774                            pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;
1775                            return 256*4096;
1776                    }
1777          if (b_mb->mode != MODE_INTER4V) {          if (b_mb->mode != MODE_INTER4V) {
1778                  iMinSAD = sad16bi(Data.Cur,                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1779                                                  get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,                          pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];
1780                                                                  x, y, 16, &pMB->mvs[0], iEdgedWidth),                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1781                                                  get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1782                                                                  x, y, 16, &pMB->b_mvs[0], iEdgedWidth), iEdgedWidth);                          break;
1783                    }
                 Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];  
                 Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];  
                 break;  
         }  
         iMinSAD += sad8bi(Data.Cur + (k&1)*8 + (k>>1)* 8 * iEdgedWidth,  
                                                 get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,  
                                                                 (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->mvs[k], iEdgedWidth),  
                                                 get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,  
                                                                 (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->b_mvs[k], iEdgedWidth),  
                                                 iEdgedWidth);  
1784          }          }
1785    
1786  // skip decision          CheckCandidate = b_mb->mode == MODE_INTER4V ? CheckCandidateDirect : CheckCandidateDirectno4v;
1787          if (iMinSAD < (int32_t)iQuant * SKIP_THRESH_B) {  
1788            CheckCandidate(0, 0, 255, &k, Data);
1789    
1790    // initial (fast) skip decision
1791            if (*Data->iMinSAD < pMB->quant * INITIAL_SKIP_THRESH * (2 + Data->chroma?1:0)) {
1792                    //possible skip
1793                    if (Data->chroma) {
1794                  pMB->mode = MODE_DIRECT_NONE_MV;                  pMB->mode = MODE_DIRECT_NONE_MV;
1795                  return iMinSAD; }                          return *Data->iMinSAD; // skip.
1796                    } else {
1797                            SkipDecisionB(pCur, f_Ref, b_Ref, pMB, x, y, Data);
1798                            if (pMB->mode == MODE_DIRECT_NONE_MV) return *Data->iMinSAD; // skip.
1799                    }
1800            }
1801    
1802          skip_sad = iMinSAD;          skip_sad = *Data->iMinSAD;
         iMinSAD += 2 * lambda_vec16[iQuant]; // 2 bits needed to code vector 0,0  
         currentMV.x = currentMV.y = 0;  
         if (b_mb->mode == MODE_INTER4V)  
                 CheckCandidate = CheckCandidateDirect;  
         else CheckCandidate = CheckCandidateDirectno4v;  
1803    
1804  //  DIRECT MODE DELTA VECTOR SEARCH.  //  DIRECT MODE DELTA VECTOR SEARCH.
1805  //      This has to be made more effective, but at the moment I'm happy it's running at all  //      This has to be made more effective, but at the moment I'm happy it's running at all
# Line 1123  Line 1808 
1808                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1809                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1810    
1811          (*MainSearchPtr)(0, 0, &Data, 255);          MainSearchPtr(0, 0, Data, 255);
1812    
1813          HalfpelRefine(&Data);          SubpelRefine(Data);
1814    
1815          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;  
1816    
1817          if (b_mb->mode == MODE_INTER4V)          if (Data->qpel || b_mb->mode == MODE_INTER4V) pMB->mode = MODE_DIRECT;
                 pMB->mode = MODE_DIRECT;  
1818          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1819    
1820          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1821    
1822          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1823                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1824                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = (     (Data->currentMV->x == 0)
1825                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1826                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          :pMB->mvs[k].x - Data->referencemv[k].x);
1827                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1828                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1829                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1830                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1831                    if (Data->qpel) {
1832                            pMB->qmvs[k].x = pMB->mvs[k].x; pMB->mvs[k].x /= 2;
1833                            pMB->b_qmvs[k].x = pMB->b_mvs[k].x; pMB->b_mvs[k].x /= 2;
1834                            pMB->qmvs[k].y = pMB->mvs[k].y; pMB->mvs[k].y /= 2;
1835                            pMB->b_qmvs[k].y = pMB->b_mvs[k].y; pMB->b_mvs[k].y /= 2;
1836                    }
1837    
1838                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1839                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1840                          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];
1841                            pMB->qmvs[3] = pMB->qmvs[2] = pMB->qmvs[1] = pMB->qmvs[0];
1842                            pMB->b_qmvs[3] = pMB->b_qmvs[2] = pMB->b_qmvs[1] = pMB->b_qmvs[0];
1843                          break;                          break;
1844                  }                  }
1845          }          }
1846          return 0;//skip_sad;          return skip_sad;
1847  }  }
1848    
1849  static __inline void  static void
1850  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const IMAGE * const f_Ref,
1851                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1852                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
1853                                  const uint8_t * const f_RefHV,                                  const uint8_t * const f_RefHV,
1854                                  const uint8_t * const b_Ref,                                  const IMAGE * const b_Ref,
1855                                  const uint8_t * const b_RefH,                                  const uint8_t * const b_RefH,
1856                                  const uint8_t * const b_RefV,                                  const uint8_t * const b_RefV,
1857                                  const uint8_t * const b_RefHV,                                  const uint8_t * const b_RefHV,
# Line 1168  Line 1860 
1860                                  const uint32_t fcode,                                  const uint32_t fcode,
1861                                  const uint32_t bcode,                                  const uint32_t bcode,
1862                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1863                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1864                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1865                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1866                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1867                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1868                                    SearchData * const fData)
1869    
1870  {  {
 /* 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;  
1871    
1872          int iDirection, i, j;          int iDirection, i, j;
1873          int32_t iMinSAD = 256*4096;          SearchData bData;
         VECTOR currentMV[3];  
         SearchData fData, bData;  
   
   
         fData.iMinSAD = bData.iMinSAD = &iMinSAD;  
1874    
1875          fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          fData->qpel_precision = 0;
1876          fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;          memcpy(&bData, fData, sizeof(SearchData)); //quick copy of common data
1877          fData.currentMV = currentMV; bData.currentMV = currentMV + 1;          *fData->iMinSAD = 4096*256;
1878          fData.iQuant = bData.iQuant = iQuant;          bData.currentMV++; bData.currentQMV++;
1879          fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;          fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1880    
1881            i = (x + y * fData->iEdgedWidth) * 16;
1882            bData.bRef = fData->Ref = f_Ref->y + i;
1883            bData.bRefH = fData->RefH = f_RefH + i;
1884            bData.bRefV = fData->RefV = f_RefV + i;
1885            bData.bRefHV = fData->RefHV = f_RefHV + i;
1886            bData.Ref = fData->bRef = b_Ref->y + i;
1887            bData.RefH = fData->bRefH = b_RefH + i;
1888            bData.RefV = fData->bRefV = b_RefV + i;
1889            bData.RefHV = fData->bRefHV = b_RefHV + i;
1890            bData.b_RefCU = fData->RefCU = f_Ref->u + (x + (fData->iEdgedWidth/2) * y) * 8;
1891            bData.b_RefCV = fData->RefCV = f_Ref->v + (x + (fData->iEdgedWidth/2) * y) * 8;
1892            bData.RefCU = fData->b_RefCU = b_Ref->u + (x + (fData->iEdgedWidth/2) * y) * 8;
1893            bData.RefCV = fData->b_RefCV = b_Ref->v + (x + (fData->iEdgedWidth/2) * y) * 8;
1894    
1895    
1896            bData.bpredMV = fData->predMV = *f_predMV;
1897            fData->bpredMV = bData.predMV = *b_predMV;
1898            fData->currentMV[0] = fData->currentMV[2];
1899    
1900            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);
1901            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);
1902    
1903            if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1904            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dx;
1905            if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dy;
1906            if (fData->currentMV[0].y < fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1907    
1908            if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1909            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dx;
1910            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dy;
1911            if (fData->currentMV[1].y < bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1912    
1913            CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
1914    
1915          bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  //diamond
         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);  
   
         CheckCandidateInt(currentMV[0].x, currentMV[0].y, 255, &iDirection, &fData);  
   
 //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  
   
1916          do {          do {
1917                  iDirection = 255;                  iDirection = 255;
1918                  // forward MV moves                  // forward MV moves
1919                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
1920    
1921                  CheckCandidateInt(i + 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1922                  CheckCandidateInt(i, j + 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1923                  CheckCandidateInt(i - 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1924                  CheckCandidateInt(i, j - 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
1925    
1926                  // backward MV moves                  // backward MV moves
1927                  i = currentMV[1].x; j = currentMV[1].y;                  i = fData->currentMV[1].x; j = fData->currentMV[1].y;
1928                  currentMV[2] = currentMV[0];                  fData->currentMV[2] = fData->currentMV[0];
1929                    CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1930                  CheckCandidateInt(i + 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1931                  CheckCandidateInt(i, j + 2, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
1932                  CheckCandidateInt(i - 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, &bData);
                 CheckCandidateInt(i, j - 2, 0, &iDirection, &bData);  
1933    
1934          } while (!(iDirection));          } while (!(iDirection));
1935    
1936  /* halfpel refinement. luckly we can use normal halfpel function for it */  //qpel refinement
1937            if (fData->qpel) {
1938          if (MotionFlags & PMV_HALFPELREFINE16) {                  if (*fData->iMinSAD > *best_sad + 500) return;
1939                  CheckCandidate = CheckCandidateInt;                  CheckCandidate = CheckCandidateInt;
1940                  HalfpelRefine(&fData);                  fData->qpel_precision = bData.qpel_precision = 1;
1941                  currentMV[2] = currentMV[0];                  get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, 1, 0);
1942                  HalfpelRefine(&bData);                  get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, 1, 0);
1943          }                  fData->currentQMV[2].x = fData->currentQMV[0].x = 2 * fData->currentMV[0].x;
1944                    fData->currentQMV[2].y = fData->currentQMV[0].y = 2 * fData->currentMV[0].y;
1945  // two bits are needed to code interpolate mode. we treat the bits just like they were vector's                  fData->currentQMV[1].x = 2 * fData->currentMV[1].x;
1946          iMinSAD +=  2 * lambda_vec16[iQuant];                  fData->currentQMV[1].y = 2 * fData->currentMV[1].y;
1947          if (iMinSAD < *best_sad) {                  SubpelRefine(fData);
1948                  *best_sad = iMinSAD;                  if (*fData->iMinSAD > *best_sad + 300) return;
1949                  pMB->mvs[0] = currentMV[0];                  fData->currentQMV[2] = fData->currentQMV[0];
1950                  pMB->b_mvs[0] = currentMV[1];                  SubpelRefine(&bData);
1951            }
1952    
1953            *fData->iMinSAD += (2+3) * fData->lambda16; // two bits are needed to code interpolate mode.
1954    
1955            if (*fData->iMinSAD < *best_sad) {
1956                    *best_sad = *fData->iMinSAD;
1957                    pMB->mvs[0] = fData->currentMV[0];
1958                    pMB->b_mvs[0] = fData->currentMV[1];
1959                  pMB->mode = MODE_INTERPOLATE;                  pMB->mode = MODE_INTERPOLATE;
1960                    if (fData->qpel) {
1961                            pMB->qmvs[0] = fData->currentQMV[0];
1962                            pMB->b_qmvs[0] = fData->currentQMV[1];
1963                            pMB->pmvs[1].x = pMB->qmvs[0].x - f_predMV->x;
1964                            pMB->pmvs[1].y = pMB->qmvs[0].y - f_predMV->y;
1965                            pMB->pmvs[0].x = pMB->b_qmvs[0].x - b_predMV->x;
1966                            pMB->pmvs[0].y = pMB->b_qmvs[0].y - b_predMV->y;
1967                    } else {
1968                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;
1969                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;
1970                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;
1971                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;
1972          }          }
1973  }  }
1974    }
1975    
1976  void  void
1977  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
# Line 1277  Line 1985 
1985                                           const IMAGE * const f_refV,                                           const IMAGE * const f_refV,
1986                                           const IMAGE * const f_refHV,                                           const IMAGE * const f_refHV,
1987                                           // backward (future) reference                                           // backward (future) reference
1988                                           const MACROBLOCK * const b_mbs,                                           const FRAMEINFO * const b_reference,
1989                                           const IMAGE * const b_ref,                                           const IMAGE * const b_ref,
1990                                           const IMAGE * const b_refH,                                           const IMAGE * const b_refH,
1991                                           const IMAGE * const b_refV,                                           const IMAGE * const b_refV,
1992                                           const IMAGE * const b_refHV)                                           const IMAGE * const b_refHV)
1993  {  {
1994          uint32_t i, j;          uint32_t i, j;
1995          int32_t best_sad, skip_sad;          int32_t best_sad;
1996            uint32_t skip_sad;
1997          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;
1998          static const VECTOR zeroMV={0,0};          const MACROBLOCK * const b_mbs = b_reference->mbs;
1999    
2000          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
2001    
2002          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
2003          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
2004    
2005          // note: i==horizontal, j==vertical  // some pre-inintialized data for the rest of the search
2006    
2007            SearchData Data;
2008            int32_t iMinSAD;
2009            VECTOR currentMV[3];
2010            VECTOR currentQMV[3];
2011            int32_t temp[8];
2012            memset(&Data, 0, sizeof(SearchData));
2013            Data.iEdgedWidth = pParam->edged_width;
2014            Data.currentMV = currentMV; Data.currentQMV = currentQMV;
2015            Data.iMinSAD = &iMinSAD;
2016            Data.lambda16 = lambda_vec16[frame->quant];
2017            Data.qpel = pParam->m_quarterpel;
2018            Data.rounding = 0;
2019            Data.chroma = frame->motion_flags & PMV_CHROMA8;
2020            Data.temp = temp;
2021    
2022            Data.RefQ = f_refV->u; // a good place, also used in MC (for similar purpose)
2023            // note: i==horizontal, j==vertical
2024          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
2025    
2026                  f_predMV = b_predMV = zeroMV;   /* prediction is reset at left boundary */                  f_predMV = b_predMV = zeroMV;   /* prediction is reset at left boundary */
# Line 1303  Line 2029 
2029                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;
2030                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;
2031    
2032  /* 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 */
2033                            if (b_reference->coding_type != S_VOP)
2034                          if (b_mb->mode == MODE_NOT_CODED) {                          if (b_mb->mode == MODE_NOT_CODED) {
2035                                  pMB->mode = MODE_NOT_CODED;                                  pMB->mode = MODE_NOT_CODED;
2036                                  continue;                                  continue;
2037                          }                          }
2038    
2039                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
2040                            Data.CurU = frame->image.u + (j * Data.iEdgedWidth/2 + i) * 8;
2041                            Data.CurV = frame->image.v + (j * Data.iEdgedWidth/2 + i) * 8;
2042                            pMB->quant = frame->quant;
2043    
2044  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
2045          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
2046                            skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
2047                          skip_sad = SearchDirect(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,
                                                                         b_ref->y, b_refH->y, b_refV->y, b_refHV->y,  
2048                                                                          &frame->image,                                                                          &frame->image,
2049                                                                          i, j,                                                                          i, j,
2050                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
2051                                                                          TRB, TRD,                                                                          TRB, TRD,
2052                                                                          pParam,                                                                          pParam,
2053                                                                          pMB, b_mb,                                                                          pMB, b_mb,
2054                                                                          &best_sad);                                                                          &best_sad,
2055                                                                            &Data);
2056    
                         if (!(frame->global_flags & XVID_HALFPEL)) best_sad = skip_sad = 256*4096;  
                         else  
2057                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
2058    
 //                      best_sad = 256*4096; //uncomment to disable Directsearch.  
 //      To disable any other mode, just comment the function call  
   
2059                          // forward search                          // forward search
2060                          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,
2061                                                  &frame->image, i, j,                                                  &frame->image, i, j,
2062                                                  frame->motion_flags,                                                  frame->motion_flags,
2063                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
2064                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
2065                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
2066    
2067                          // backward search                          // backward search
2068                          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,
2069                                                  &frame->image, i, j,                                                  &frame->image, i, j,
2070                                                  frame->motion_flags,                                                  frame->motion_flags,
2071                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
2072                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
2073                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
2074    
2075                          // 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
2076                            SearchInterpolate(f_ref, f_refH->y, f_refV->y, f_refHV->y,
2077                          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,  
2078                                                  &frame->image,                                                  &frame->image,
2079                                                  i, j,                                                  i, j,
2080                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
2081                                                  frame->motion_flags,                                                  frame->motion_flags,
2082                                                  frame->quant, pParam,                                                  pParam,
2083                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
2084                                                  pMB, &best_sad);                                                  pMB, &best_sad,
2085                                                    &Data);
2086    
2087    // final skip decision
2088                            if ( (skip_sad < frame->quant * MAX_SAD00_FOR_SKIP * 2)
2089                                            && ((100*best_sad)/(skip_sad+1) > FINAL_SKIP_THRESH) )
2090                                    SkipDecisionB(&frame->image, f_ref, b_ref, pMB, i, j, &Data);
2091    
2092                          switch (pMB->mode) {                          switch (pMB->mode) {
2093                                  case MODE_FORWARD:                                  case MODE_FORWARD:
2094                                          f_count++;                                          f_count++;
2095                                          f_predMV = pMB->mvs[0];                                          f_predMV = Data.qpel ? pMB->qmvs[0] : pMB->mvs[0];
2096                                          break;                                          break;
2097                                  case MODE_BACKWARD:                                  case MODE_BACKWARD:
2098                                          b_count++;                                          b_count++;
2099                                          b_predMV = pMB->b_mvs[0];                                          b_predMV = Data.qpel ? pMB->b_qmvs[0] : pMB->b_mvs[0];
2100                                          break;                                          break;
2101                                  case MODE_INTERPOLATE:                                  case MODE_INTERPOLATE:
2102                                          i_count++;                                          i_count++;
2103                                          f_predMV = pMB->mvs[0];                                          f_predMV = Data.qpel ? pMB->qmvs[0] : pMB->mvs[0];
2104                                          b_predMV = pMB->b_mvs[0];                                          b_predMV = Data.qpel ? pMB->b_qmvs[0] : pMB->b_mvs[0];
2105                                          break;                                          break;
2106                                  case MODE_DIRECT:                                  case MODE_DIRECT:
2107                                  case MODE_DIRECT_NO4V:                                  case MODE_DIRECT_NO4V:
2108                                          d_count++;                                          d_count++;
                                         break;  
2109                                  default:                                  default:
2110                                          break;                                          break;
2111                          }                          }
2112                  }                  }
2113          }          }
   
 //      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);  
   
2114  }  }
2115    
 /* Hinted ME starts here */  
   
2116  static __inline void  static __inline void
2117  Search8hinted(  const SearchData * const OldData,  MEanalyzeMB (   const uint8_t * const pRef,
2118                                  const int x, const int y,                                  const uint8_t * const pCur,
2119                                  const uint32_t MotionFlags,                                  const int x,
2120                                    const int y,
2121                                  const MBParam * const pParam,                                  const MBParam * const pParam,
2122                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMBs,
2123                                  const MACROBLOCK * const pMBs,                                  SearchData * const Data)
                                 const int block)  
2124  {  {
         SearchData Data;  
         MainSearchFunc *MainSearchPtr;  
2125    
2126          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          int i, mask;
2127          Data.iMinSAD = OldData->iMinSAD + 1 + block;          VECTOR pmv[3];
2128          Data.currentMV = OldData->currentMV+1+block;          MACROBLOCK * pMB = &pMBs[x + y * pParam->mb_width];
2129          Data.iFcode = OldData->iFcode;  
2130          Data.iQuant = OldData->iQuant;          for (i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
   
         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));  
2131    
2132          CheckCandidate = CheckCandidate8;          //median is only used as prediction. it doesn't have to be real
2133            if (x == 1 && y == 1) Data->predMV.x = Data->predMV.y = 0;
2134            else
2135                    if (x == 1) //left macroblock does not have any vector now
2136                            Data->predMV = (pMB - pParam->mb_width)->mvs[0]; // top instead of median
2137                    else if (y == 1) // top macroblock doesn't have it's vector
2138                            Data->predMV = (pMB - 1)->mvs[0]; // left instead of median
2139                            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); //else median
2140    
2141          if (block != 0)          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2142                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *                                  pParam->width, pParam->height, Data->iFcode - pParam->m_quarterpel, 0, Data->rrv);
                                                                 d_mv_bits(      Data.currentMV->x - Data.predMV.x,  
                                                                                         Data.currentMV->y - Data.predMV.y,  
                                                                                         Data.iFcode);  
2143    
2144            Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
2145            Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
2146    
2147          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,          pmv[1].x = EVEN(pMB->mvs[0].x);
2148                                  pParam->width, pParam->height, OldData->iFcode);          pmv[1].y = EVEN(pMB->mvs[0].y);
2149            pmv[2].x = EVEN(Data->predMV.x);
2150            pmv[2].y = EVEN(Data->predMV.y);
2151            pmv[0].x = pmv[0].y = 0;
2152    
2153          if (pMB->mode == MODE_INTER4V) {          CheckCandidate32I(0, 0, 255, &i, Data);
                 int dummy;  
                 CheckCandidate8(pMB->mvs[block].x, pMB->mvs[block].y, 0, &dummy, &Data); }  
2154    
2155          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;          if (*Data->iMinSAD > 4 * MAX_SAD00_FOR_SKIP * 4) {
                 else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;  
                         else MainSearchPtr = DiamondSearch;  
2156    
2157          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);                  if (!(mask = make_mask(pmv, 1)))
2158                            CheckCandidate32I(pmv[1].x, pmv[1].y, mask, &i, Data);
2159                    if (!(mask = make_mask(pmv, 2)))
2160                            CheckCandidate32I(pmv[2].x, pmv[2].y, mask, &i, Data);
2161    
2162          if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                  if (*Data->iMinSAD > 4 * MAX_SAD00_FOR_SKIP * 4) // diamond only if needed
2163                            DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
2164    
2165          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;                  for (i = 0; i < 4; i++) {
2166          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;                          MACROBLOCK * MB = &pMBs[x + (i&1) + (y+(i>>1)) * pParam->mb_width];
2167          pMB->mvs[block] = *(Data.currentMV);                          MB->mvs[0] = MB->mvs[1] = MB->mvs[2] = MB->mvs[3] = Data->currentMV[i];
2168          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                          MB->mode = MODE_INTER;
2169                            MB->sad16 = Data->iMinSAD[i+1];
2170                    }
2171            }
2172  }  }
2173    
2174    #define INTRA_BIAS              2500
2175    #define INTRA_THRESH    1500
2176    #define INTER_THRESH    1400
2177    
2178  static void  int
2179  SearchPhinted ( const uint8_t * const pRef,  MEanalysis(     const IMAGE * const pRef,
2180                                  const uint8_t * const pRefH,                          FRAMEINFO * const Current,
2181                                  const uint8_t * const pRefV,                          MBParam * const pParam,
2182                                  const uint8_t * const pRefHV,                          int maxIntra, //maximum number if non-I frames
2183                                  const IMAGE * const pCur,                          int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame
2184                                  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)  
2185  {  {
2186            uint32_t x, y, intra = 0;
2187            int sSAD = 0;
2188            MACROBLOCK * const pMBs = Current->mbs;
2189            const IMAGE * const pCurrent = &Current->image;
2190            int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH;
2191    
2192          const int32_t iEdgedWidth = pParam->edged_width;          int32_t iMinSAD[5], temp[5];
   
         int i;  
2193          VECTOR currentMV[5];          VECTOR currentMV[5];
         int32_t iMinSAD[5];  
         int32_t temp[5];  
         MainSearchFunc * MainSearchPtr;  
2194          SearchData Data;          SearchData Data;
2195            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;  
2196          Data.currentMV = currentMV;          Data.currentMV = currentMV;
2197          Data.iMinSAD = iMinSAD;          Data.iMinSAD = iMinSAD;
2198          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data.iFcode = Current->fcode;
2199          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;  
2200          Data.temp = temp;          Data.temp = temp;
2201          Data.iQuant = iQuant;          CheckCandidate = CheckCandidate32I;
2202          Data.iFcode = iFcode;  
2203            if (intraCount != 0 && intraCount < 10) // we're right after an I frame
2204                    IntraThresh += 4 * (intraCount - 10) * (intraCount - 10);
2205            else
2206                    if ( 5*(maxIntra - intraCount) < maxIntra) // we're close to maximum. 2 sec when max is 10 sec
2207                            IntraThresh -= (IntraThresh * (maxIntra - 5*(maxIntra - intraCount)))/maxIntra;
2208    
2209          if (!(MotionFlags & PMV_HALFPEL16)) {          InterThresh += 400 * (1 - bCount);
2210                  Data.min_dx = EVEN(Data.min_dx);          if (InterThresh < 300) InterThresh = 300;
2211                  Data.max_dx = EVEN(Data.max_dx);  
2212                  Data.min_dy = EVEN(Data.min_dy);          if (sadInit) (*sadInit) ();
2213                  Data.max_dy = EVEN(Data.max_dy);  
2214            for (y = 1; y < pParam->mb_height-1; y += 2) {
2215                    for (x = 1; x < pParam->mb_width-1; x += 2) {
2216                            int i;
2217    
2218                            if (bCount == 0) pMBs[x + y * pParam->mb_width].mvs[0] = zeroMV;
2219    
2220                            MEanalyzeMB(pRef->y, pCurrent->y, x, y, pParam, pMBs, &Data);
2221    
2222                            for (i = 0; i < 4; i++) {
2223                                    int dev;
2224                                    MACROBLOCK *pMB = &pMBs[x+(i&1) + (y+(i>>1)) * pParam->mb_width];
2225                                    if (pMB->sad16 > IntraThresh) {
2226                                            dev = dev16(pCurrent->y + (x + (i&1) + (y + (i>>1)) * pParam->edged_width) * 16,
2227                                                                            pParam->edged_width);
2228                                            if (dev + IntraThresh < pMB->sad16) {
2229                                                    pMB->mode = MODE_INTRA;
2230                                                    if (++intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return I_VOP;
2231                                            }
2232                                    }
2233                                    sSAD += pMB->sad16;
2234                            }
2235                    }
2236          }          }
2237            sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2238    //      if (sSAD > IntraThresh + INTRA_BIAS) return I_VOP;
2239            if (sSAD > InterThresh ) return P_VOP;
2240            emms();
2241            return B_VOP;
2242    
2243          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;  }
2244    
         if (pMB->dquant != NO_CHANGE) inter4v = 0;  
2245    
2246          if (inter4v)  static WARPPOINTS
2247                  CheckCandidate = CheckCandidate16;  GlobalMotionEst(const MACROBLOCK * const pMBs,
2248          else CheckCandidate = CheckCandidate16no4v;                                  const MBParam * const pParam,
2249                                    const FRAMEINFO * const current,
2250                                    const FRAMEINFO * const reference,
2251                                    const IMAGE * const pRefH,
2252                                    const IMAGE * const pRefV,
2253                                    const IMAGE * const pRefHV      )
2254    {
2255    
2256            const int deltax=8;             // upper bound for difference between a MV and it's neighbour MVs
2257            const int deltay=8;
2258            const int grad=512;             // lower bound for deviation in MB
2259    
2260          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);          WARPPOINTS gmc;
         pMB->mvs[0].y = EVEN(pMB->mvs[0].y);  
         if (pMB->mvs[0].x > Data.max_dx) pMB->mvs[0].x = Data.max_dx; // this is in case iFcode changed  
         if (pMB->mvs[0].x < Data.min_dx) pMB->mvs[0].x = Data.min_dx;  
         if (pMB->mvs[0].y > Data.max_dy) pMB->mvs[0].y = Data.max_dy;  
         if (pMB->mvs[0].y < Data.min_dy) pMB->mvs[0].y = Data.min_dy;  
   
         CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);  
   
         if (pMB->mode == MODE_INTER4V)  
                 for (i = 1; i < 4; i++) { // all four vectors will be used as four predictions for 16x16 search  
                         pMB->mvs[i].x = EVEN(pMB->mvs[i].x);  
                         pMB->mvs[i].y = EVEN(pMB->mvs[i].y);  
                         if (!(make_mask(pMB->mvs, i)))  
                                 CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);  
                 }  
   
         if (MotionFlags & PMV_USESQUARES16)  
                 MainSearchPtr = SquareSearch;  
         else if (MotionFlags & PMV_ADVANCEDDIAMOND16)  
                 MainSearchPtr = AdvDiamondSearch;  
                 else MainSearchPtr = DiamondSearch;  
2261    
2262          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          uint32_t mx, my;
2263    
2264          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          int MBh = pParam->mb_height;
2265            int MBw = pParam->mb_width;
2266    
2267          if (inter4v)          int *MBmask= calloc(MBh*MBw,sizeof(int));
2268                  for(i = 0; i < 4; i++)          double DtimesF[4] = { 0.,0., 0., 0. };
2269                          Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);          double sol[4] = { 0., 0., 0., 0. };
2270            double a,b,c,n,denom;
2271            double meanx,meany;
2272            int num,oldnum;
2273    
2274          if (!(inter4v) ||          if (!MBmask) { fprintf(stderr,"Mem error\n"); return gmc;}
                 (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {  
 // INTER MODE  
2275    
2276                  pMB->mode = MODE_INTER;  // filter mask of all blocks
                 pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]  
                         = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];  
2277    
2278                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =          for (my = 1; my < MBh-1; my++)
2279                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];          for (mx = 1; mx < MBw-1; mx++)
2280            {
2281                    const int mbnum = mx + my * MBw;
2282                    const MACROBLOCK *pMB = &pMBs[mbnum];
2283                    const VECTOR mv = pMB->mvs[0];
2284    
2285                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
2286                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          continue;
2287    
2288                    if ( ( (ABS(mv.x -   (pMB-1)->mvs[0].x) < deltax) && (ABS(mv.y -   (pMB-1)->mvs[0].y) < deltay) )
2289                    &&   ( (ABS(mv.x -   (pMB+1)->mvs[0].x) < deltax) && (ABS(mv.y -   (pMB+1)->mvs[0].y) < deltay) )
2290                    &&   ( (ABS(mv.x - (pMB-MBw)->mvs[0].x) < deltax) && (ABS(mv.y - (pMB-MBw)->mvs[0].y) < deltay) )
2291                    &&   ( (ABS(mv.x - (pMB+MBw)->mvs[0].x) < deltax) && (ABS(mv.y - (pMB+MBw)->mvs[0].y) < deltay) ) )
2292                            MBmask[mbnum]=1;
2293            }
2294    
2295            for (my = 1; my < MBh-1; my++)
2296            for (mx = 1; mx < MBw-1; mx++)
2297            {
2298                    const uint8_t *const pCur = current->image.y + 16*my*pParam->edged_width + 16*mx;
2299    
2300                    const int mbnum = mx + my * MBw;
2301                    if (!MBmask[mbnum])
2302                            continue;
2303    
2304                    if (sad16 ( pCur, pCur+1 , pParam->edged_width, 65536) <= grad )
2305                            MBmask[mbnum] = 0;
2306                    if (sad16 ( pCur, pCur+pParam->edged_width, pParam->edged_width, 65536) <= grad )
2307                            MBmask[mbnum] = 0;
2308    
2309            }
2310    
2311            emms();
2312    
2313            do {            /* until convergence */
2314    
2315            a = b = c = n = 0;
2316            DtimesF[0] = DtimesF[1] = DtimesF[2] = DtimesF[3] = 0.;
2317            for (my = 0; my < MBh; my++)
2318                    for (mx = 0; mx < MBw; mx++)
2319                    {
2320                            const int mbnum = mx + my * MBw;
2321                            const MACROBLOCK *pMB = &pMBs[mbnum];
2322                            const VECTOR mv = pMB->mvs[0];
2323    
2324                            if (!MBmask[mbnum])
2325                                    continue;
2326    
2327                            n++;
2328                            a += 16*mx+8;
2329                            b += 16*my+8;
2330                            c += (16*mx+8)*(16*mx+8)+(16*my+8)*(16*my+8);
2331    
2332                            DtimesF[0] += (double)mv.x;
2333                            DtimesF[1] += (double)mv.x*(16*mx+8) + (double)mv.y*(16*my+8);
2334                            DtimesF[2] += (double)mv.x*(16*my+8) - (double)mv.y*(16*mx+8);
2335                            DtimesF[3] += (double)mv.y;
2336                    }
2337    
2338            denom = a*a+b*b-c*n;
2339    
2340    /* Solve the system:     sol = (D'*E*D)^{-1} D'*E*F   */
2341    /* D'*E*F has been calculated in the same loop as matrix */
2342    
2343            sol[0] = -c*DtimesF[0] + a*DtimesF[1] + b*DtimesF[2];
2344            sol[1] =  a*DtimesF[0] - n*DtimesF[1]                + b*DtimesF[3];
2345            sol[2] =  b*DtimesF[0]                - n*DtimesF[2] - a*DtimesF[3];
2346            sol[3] =                 b*DtimesF[1] - a*DtimesF[2] - c*DtimesF[3];
2347    
2348            sol[0] /= denom;
2349            sol[1] /= denom;
2350            sol[2] /= denom;
2351            sol[3] /= denom;
2352    
2353            meanx = meany = 0.;
2354            oldnum = 0;
2355            for (my = 0; my < MBh; my++)
2356                    for (mx = 0; mx < MBw; mx++)
2357                    {
2358                            const int mbnum = mx + my * MBw;
2359                            const MACROBLOCK *pMB = &pMBs[mbnum];
2360                            const VECTOR mv = pMB->mvs[0];
2361    
2362                            if (!MBmask[mbnum])
2363                                    continue;
2364    
2365                            oldnum++;
2366                            meanx += ABS(( sol[0] + (16*mx+8)*sol[1] + (16*my+8)*sol[2] ) - mv.x );
2367                            meany += ABS(( sol[3] - (16*mx+8)*sol[2] + (16*my+8)*sol[1] ) - mv.y );
2368                    }
2369    
2370            if (4*meanx > oldnum)   /* better fit than 0.25 is useless */
2371                    meanx /= oldnum;
2372            else
2373                    meanx = 0.25;
2374    
2375            if (4*meany > oldnum)
2376                    meany /= oldnum;
2377            else
2378                    meany = 0.25;
2379    
2380    /*      fprintf(stderr,"sol = (%8.5f, %8.5f, %8.5f, %8.5f)\n",sol[0],sol[1],sol[2],sol[3]);
2381            fprintf(stderr,"meanx = %8.5f  meany = %8.5f   %d\n",meanx,meany, oldnum);
2382    */
2383            num = 0;
2384            for (my = 0; my < MBh; my++)
2385                    for (mx = 0; mx < MBw; mx++)
2386                    {
2387                            const int mbnum = mx + my * MBw;
2388                            const MACROBLOCK *pMB = &pMBs[mbnum];
2389                            const VECTOR mv = pMB->mvs[0];
2390    
2391                            if (!MBmask[mbnum])
2392                                    continue;
2393    
2394                            if  ( ( ABS(( sol[0] + (16*mx+8)*sol[1] + (16*my+8)*sol[2] ) - mv.x ) > meanx )
2395                               || ( ABS(( sol[3] - (16*mx+8)*sol[2] + (16*my+8)*sol[1] ) - mv.y ) > meany ) )
2396                                    MBmask[mbnum]=0;
2397                            else
2398                                    num++;
2399                    }
2400    
2401            } while ( (oldnum != num) && (num>=4) );
2402    
2403            if (num < 4)
2404            {
2405                    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;
2406          } else {          } else {
2407  // INTER4V MODE; all other things are already set in Search8hinted  
2408                  pMB->mode = MODE_INTER4V;                  gmc.duv[0].x=(int)(sol[0]+0.5);
2409                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  gmc.duv[0].y=(int)(sol[3]+0.5);
2410    
2411                    gmc.duv[1].x=(int)(sol[1]*pParam->width+0.5);
2412                    gmc.duv[1].y=(int)(-sol[2]*pParam->width+0.5);
2413    
2414                    gmc.duv[2].x=0;
2415                    gmc.duv[2].y=0;
2416          }          }
2417    //      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);
2418    
2419            free(MBmask);
2420    
2421            return gmc;
2422  }  }
2423    
2424  void  // functions which perform BITS-based search/bitcount
2425  MotionEstimationHinted( MBParam * const pParam,  
2426                                                  FRAMEINFO * const current,  static int
2427                                                  FRAMEINFO * const reference,  CountMBBitsInter(SearchData * const Data,
2428                                                  const IMAGE * const pRefH,                                  const MACROBLOCK * const pMBs, const int x, const int y,
2429                                                  const IMAGE * const pRefV,                                  const MBParam * const pParam,
2430                                                  const IMAGE * const pRefHV)                                  const uint32_t MotionFlags)
2431  {  {
2432          MACROBLOCK *const pMBs = current->mbs;          int i, iDirection;
2433          const IMAGE *const pCurrent = &current->image;          int32_t bsad[5];
         const IMAGE *const pRef = &reference->image;  
2434    
2435          uint32_t x, y;          CheckCandidate = CheckCandidateBits16;
2436    
2437          if (sadInit) (*sadInit) ();          if (Data->qpel) {
2438                    for(i = 0; i < 5; i++) {
2439                            Data->currentMV[i].x = Data->currentQMV[i].x/2;
2440                            Data->currentMV[i].y = Data->currentQMV[i].y/2;
2441                    }
2442                    Data->qpel_precision = 1;
2443                    CheckCandidateBits16(Data->currentQMV[0].x, Data->currentQMV[0].y, 255, &iDirection, Data);
2444    
2445          for (y = 0; y < pParam->mb_height; y++) {                  //checking if this vector is perfect. if it is, we stop.
2446                  for (x = 0; x < pParam->mb_width; x++)  {                  if (Data->temp[0] == 0 && Data->temp[1] == 0 && Data->temp[2] == 0 && Data->temp[3] == 0)
2447                          int32_t sad00;                          return 0; //quick stop
2448    
2449                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                  if (MotionFlags & (HALFPELREFINE16_BITS | EXTSEARCH_BITS)) { //we have to prepare for halfpixel-precision search
2450                            for(i = 0; i < 5; i++) bsad[i] = Data->iMinSAD[i];
2451                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2452                                                    pParam->width, pParam->height, Data->iFcode - Data->qpel, 0, Data->rrv);
2453                            Data->qpel_precision = 0;
2454                            if (Data->currentQMV->x & 1 || Data->currentQMV->y & 1)
2455                                    CheckCandidateBits16(Data->currentMV[0].x, Data->currentMV[0].y, 255, &iDirection, Data);
2456                    }
2457    
2458  //intra mode is copied from the first pass. At least for the time being          } else { // not qpel
                         if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;  
2459    
2460                          if (!(current->global_flags & XVID_LUMIMASKING)) {                  CheckCandidateBits16(Data->currentMV[0].x, Data->currentMV[0].y, 255, &iDirection, Data);
2461                                  pMB->dquant = NO_CHANGE;                  //checking if this vector is perfect. if it is, we stop.
2462                                  pMB->quant = current->quant; }                  if (Data->temp[0] == 0 && Data->temp[1] == 0 && Data->temp[2] == 0 && Data->temp[3] == 0) {
2463                            return 0; //inter
2464                    }
2465            }
2466    
2467                          if (pMB->dquant == NO_CHANGE) //no skip otherwise, anyway          if (MotionFlags&EXTSEARCH_BITS) SquareSearch(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
                                 sad00 = pMB->sad16  
                                         = sad16(pCurrent->y + (x + y * pParam->edged_width) * 16,  
                                                                 pRef->y + (x + y * pParam->edged_width) * 16,  
                                                                 pParam->edged_width, 256*4096 );  
                         else sad00 = 256*4096;  
2468    
2469            if (MotionFlags&HALFPELREFINE16_BITS) SubpelRefine(Data);
2470    
2471  //initial skip decision          if (Data->qpel) {
2472                    if (MotionFlags&(EXTSEARCH_BITS | HALFPELREFINE16_BITS)) { // there was halfpel-precision search
2473                            for(i = 0; i < 5; i++) if (bsad[i] > Data->iMinSAD[i]) {
2474                                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // we have found a better match
2475                                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
2476                            }
2477    
2478                          if ( (pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)                          // preparing for qpel-precision search
2479                                  && ( //(pMB->mode == MODE_NOT_CODED) ||                          Data->qpel_precision = 1;
2480                                          (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant) )) ) {                          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2481                                  if (sad00 < pMB->quant * INITIAL_SKIP_THRESH) {                                          pParam->width, pParam->height, Data->iFcode, 1, 0);
2482                                          SkipMacroblockP(pMB, sad00);                  }
2483                                          continue; } //skipped                  if (MotionFlags&QUARTERPELREFINE16_BITS) SubpelRefine(Data);
2484                          }                          }
                         else sad00 = 256*4096;  
2485    
2486                          if (pMB->mode == MODE_NOT_CODED)          if (MotionFlags&CHECKPREDICTION_BITS) { //let's check vector equal to prediction
2487                                  SearchP(        pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                  VECTOR * v = Data->qpel ? Data->currentQMV : Data->currentMV;
2488                                                          y, current->motion_flags, pMB->quant,                  if (!(Data->predMV.x == v->x && Data->predMV.y == v->y))
2489                                                          current->fcode, pParam, pMBs, reference->mbs,                          CheckCandidateBits16(Data->predMV.x, Data->predMV.y, 255, &iDirection, Data);
2490                                                          current->global_flags & XVID_INTER4V, pMB);          }
2491            return Data->iMinSAD[0];
2492    }
2493    
                         else  
                                 SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,  
                                                         y, current->motion_flags, pMB->quant,  
                                                         current->fcode, pParam, pMBs,  
                                                         current->global_flags & XVID_INTER4V, pMB);  
2494    
2495  /* final skip decision, a.k.a. "the vector you found, really that good?" */  static int
2496                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)  CountMBBitsInter4v(const SearchData * const Data,
2497                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)                                          MACROBLOCK * const pMB, const MACROBLOCK * const pMBs,
2498                                  SkipMacroblockP(pMB, sad00);                                          const int x, const int y,
2499                                            const MBParam * const pParam, const uint32_t MotionFlags,
2500                                            const VECTOR * const backup)
2501    {
2502    
2503            int cbp = 0, bits = 0, t = 0, i, iDirection;
2504            SearchData Data2, *Data8 = &Data2;
2505            int sumx = 0, sumy = 0;
2506            int16_t in[64], coeff[64];
2507    
2508            memcpy(Data8, Data, sizeof(SearchData));
2509            CheckCandidate = CheckCandidateBits8;
2510    
2511            for (i = 0; i < 4; i++) {
2512                    Data8->iMinSAD = Data->iMinSAD + i + 1;
2513                    Data8->currentMV = Data->currentMV + i + 1;
2514                    Data8->currentQMV = Data->currentQMV + i + 1;
2515                    Data8->Cur = Data->Cur + 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2516                    Data8->Ref = Data->Ref + 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2517                    Data8->RefH = Data->RefH + 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2518                    Data8->RefV = Data->RefV + 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2519                    Data8->RefHV = Data->RefHV + 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2520    
2521                    if(Data->qpel) {
2522                            Data8->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, i);
2523                            if (i != 0)     t = d_mv_bits(  Data8->currentQMV->x, Data8->currentQMV->y,
2524                                                                                    Data8->predMV, Data8->iFcode, 0, 0);
2525                    } else {
2526                            Data8->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, i);
2527                            if (i != 0)     t = d_mv_bits(  Data8->currentMV->x, Data8->currentMV->y,
2528                                                                                    Data8->predMV, Data8->iFcode, 0, 0);
2529                  }                  }
2530    
2531                    get_range(&Data8->min_dx, &Data8->max_dx, &Data8->min_dy, &Data8->max_dy, 2*x + (i&1), 2*y + (i>>1), 8,
2532                                            pParam->width, pParam->height, Data8->iFcode, Data8->qpel, 0);
2533    
2534                    *Data8->iMinSAD += t;
2535    
2536                    Data8->qpel_precision = Data8->qpel;
2537                    // checking the vector which has been found by SAD-based 8x8 search (if it's different than the one found so far)
2538                    if (Data8->qpel) {
2539                            if (!(Data8->currentQMV->x == backup[i+1].x && Data8->currentQMV->y == backup[i+1].y))
2540                                    CheckCandidateBits8(backup[i+1].x, backup[i+1].y, 255, &iDirection, Data8);
2541                    } else {
2542                            if (!(Data8->currentMV->x == backup[i+1].x && Data8->currentMV->y == backup[i+1].y))
2543                                    CheckCandidateBits8(backup[i+1].x, backup[i+1].y, 255, &iDirection, Data8);
2544                    }
2545    
2546                    if (Data8->qpel) {
2547                            if (MotionFlags&HALFPELREFINE8_BITS || (MotionFlags&PMV_EXTSEARCH8 && MotionFlags&EXTSEARCH_BITS)) { // halfpixel motion search follows
2548                                    int32_t s = *Data8->iMinSAD;
2549                                    Data8->currentMV->x = Data8->currentQMV->x/2;
2550                                    Data8->currentMV->y = Data8->currentQMV->y/2;
2551                                    Data8->qpel_precision = 0;
2552                                    get_range(&Data8->min_dx, &Data8->max_dx, &Data8->min_dy, &Data8->max_dy, 2*x + (i&1), 2*y + (i>>1), 8,
2553                                                            pParam->width, pParam->height, Data8->iFcode - 1, 0, 0);
2554    
2555                                    if (Data8->currentQMV->x & 1 || Data8->currentQMV->y & 1)
2556                                            CheckCandidateBits8(Data8->currentMV->x, Data8->currentMV->y, 255, &iDirection, Data8);
2557    
2558                                    if (MotionFlags & PMV_EXTSEARCH8 && MotionFlags & EXTSEARCH_BITS)
2559                                            SquareSearch(Data8->currentMV->x, Data8->currentMV->x, Data8, 255);
2560    
2561                                    if (MotionFlags & HALFPELREFINE8_BITS) SubpelRefine(Data8);
2562    
2563                                    if(s > *Data8->iMinSAD) { //we have found a better match
2564                                            Data8->currentQMV->x = 2*Data8->currentMV->x;
2565                                            Data8->currentQMV->y = 2*Data8->currentMV->y;
2566                                    }
2567    
2568                                    Data8->qpel_precision = 1;
2569                                    get_range(&Data8->min_dx, &Data8->max_dx, &Data8->min_dy, &Data8->max_dy, 2*x + (i&1), 2*y + (i>>1), 8,
2570                                                            pParam->width, pParam->height, Data8->iFcode, 1, 0);
2571    
2572                            }
2573                            if (MotionFlags & QUARTERPELREFINE8_BITS) SubpelRefine(Data8);
2574    
2575                    } else // not qpel
2576                            if (MotionFlags & HALFPELREFINE8_BITS) SubpelRefine(Data8); //halfpel mode, halfpel refinement
2577    
2578                    //checking vector equal to predicion
2579                    if (i != 0 && MotionFlags & CHECKPREDICTION_BITS) {
2580                            const VECTOR * v = Data->qpel ? Data8->currentQMV : Data8->currentMV;
2581                            if (!(Data8->predMV.x == v->x && Data8->predMV.y == v->y))
2582                                    CheckCandidateBits8(Data8->predMV.x, Data8->predMV.y, 255, &iDirection, Data8);
2583                    }
2584    
2585                    bits += *Data8->iMinSAD;
2586                    if (bits >= Data->iMinSAD[0]) break; // no chances for INTER4V
2587    
2588                    // MB structures for INTER4V mode; we have to set them here, we don't have predictor anywhere else
2589                    if(Data->qpel) {
2590                            pMB->pmvs[i].x = Data8->currentQMV->x - Data8->predMV.x;
2591                            pMB->pmvs[i].y = Data8->currentQMV->y - Data8->predMV.y;
2592                            pMB->qmvs[i] = *Data8->currentQMV;
2593                            sumx += Data8->currentQMV->x/2;
2594                            sumy += Data8->currentQMV->y/2;
2595                    } else {
2596                            pMB->pmvs[i].x = Data8->currentMV->x - Data8->predMV.x;
2597                            pMB->pmvs[i].y = Data8->currentMV->y - Data8->predMV.y;
2598                            sumx += Data8->currentMV->x;
2599                            sumy += Data8->currentMV->y;
2600                    }
2601                    pMB->mvs[i] = *Data8->currentMV;
2602                    pMB->sad8[i] = 4 * *Data8->iMinSAD;
2603                    if (Data8->temp[0]) cbp |= 1 << (5 - i);
2604            }
2605    
2606            if (bits < *Data->iMinSAD) { // there is still a chance for inter4v mode. let's check chroma
2607                    const uint8_t * ptr;
2608                    sumx = (sumx >> 3) + roundtab_76[sumx & 0xf];
2609                    sumy = (sumy >> 3) + roundtab_76[sumy & 0xf];
2610    
2611                    //chroma U
2612                    ptr = interpolate8x8_switch2(Data->RefQ + 64, Data->RefCU, 0, 0, sumx, sumy, Data->iEdgedWidth/2, Data->rounding);
2613                    transfer_8to16subro(in, Data->CurU, ptr, Data->iEdgedWidth/2);
2614                    fdct(in);
2615                    if (Data->lambda8 == 0) i = quant_inter(coeff, in, Data->lambda16);
2616                    else i = quant4_inter(coeff, in, Data->lambda16);
2617                    if (i > 0) {
2618                            bits += CodeCoeffInter_CalcBits(coeff, scan_tables[0]);
2619                            cbp |= 1 << (5 - 4);
2620                    }
2621    
2622                    if (bits < *Data->iMinSAD) { // still possible
2623                            //chroma V
2624                            ptr = interpolate8x8_switch2(Data->RefQ + 64, Data->RefCV, 0, 0, sumx, sumy, Data->iEdgedWidth/2, Data->rounding);
2625                            transfer_8to16subro(in, Data->CurV, ptr, Data->iEdgedWidth/2);
2626                            fdct(in);
2627                            if (Data->lambda8 == 0) i = quant_inter(coeff, in, Data->lambda16);
2628                            else i = quant4_inter(coeff, in, Data->lambda16);
2629                            if (i > 0) {
2630                                    bits += CodeCoeffInter_CalcBits(coeff, scan_tables[0]);
2631                                    cbp |= 1 << (5 - 5);
2632                            }
2633                            bits += cbpy_tab[15-(cbp>>2)].len;
2634                            bits += mcbpc_inter_tab[(MODE_INTER4V & 7) | ((cbp & 3) << 3)].len;
2635                    }
2636            }
2637    
2638            return bits;
2639    }
2640    
2641    
2642    static int
2643    CountMBBitsIntra(const SearchData * const Data)
2644    {
2645            int bits = 1; //this one is ac/dc prediction flag. always 1.
2646            int cbp = 0, i, t, dc = 0, b_dc = 1024;
2647            const uint32_t iQuant = Data->lambda16;
2648            int16_t in[64], coeff[64];
2649    
2650            for(i = 0; i < 4; i++) {
2651                    uint32_t iDcScaler = get_dc_scaler(iQuant, 1);
2652    
2653                    int s = 8*((i&1) + (i>>1)*Data->iEdgedWidth);
2654                    transfer_8to16copy(in, Data->Cur + s, Data->iEdgedWidth);
2655                    fdct(in);
2656                    b_dc = dc;
2657                    dc = in[0];
2658                    in[0] -= b_dc;
2659                    if (Data->lambda8 == 0) quant_intra_c(coeff, in, iQuant, iDcScaler);
2660                    else quant4_intra_c(coeff, in, iQuant, iDcScaler);
2661    
2662                    b_dc = dc;
2663                    dc = coeff[0];
2664                    if (i != 0) coeff[0] -= b_dc;
2665    
2666                    bits += t = CodeCoeffIntra_CalcBits(coeff, scan_tables[0]) + dcy_tab[coeff[0] + 255].len;;
2667                    Data->temp[i] = t;
2668                    if (t != 0)  cbp |= 1 << (5 - i);
2669                    if (bits >= Data->iMinSAD[0]) break;
2670            }
2671    
2672            if (bits < Data->iMinSAD[0]) { // INTRA still looks good, let's add chroma
2673                    uint32_t iDcScaler = get_dc_scaler(iQuant, 0);
2674                    //chroma U
2675                    transfer_8to16copy(in, Data->CurU, Data->iEdgedWidth/2);
2676                    fdct(in);
2677                    in[0] -= 1024;
2678                    if (Data->lambda8 == 0) quant_intra(coeff, in, iQuant, iDcScaler);
2679                    else quant4_intra(coeff, in, iQuant, iDcScaler);
2680    
2681                    bits += t = CodeCoeffIntra_CalcBits(coeff, scan_tables[0]) + dcc_tab[coeff[0] + 255].len;
2682                    if (t != 0) cbp |= 1 << (5 - 4);
2683                    Data->temp[4] = t;
2684    
2685                    if (bits < Data->iMinSAD[0]) {
2686                            //chroma V
2687                            transfer_8to16copy(in, Data->CurV, Data->iEdgedWidth/2);
2688                            fdct(in);
2689                            in[0] -= 1024;
2690                            if (Data->lambda8 == 0) quant_intra(coeff, in, iQuant, iDcScaler);
2691                            else quant4_intra(coeff, in, iQuant, iDcScaler);
2692    
2693                            bits += t = CodeCoeffIntra_CalcBits(coeff, scan_tables[0]) + dcc_tab[coeff[0] + 255].len;
2694                            if (t != 0) cbp |= 1 << (5 - 5);
2695    
2696                            Data->temp[5] = t;
2697    
2698                            bits += t = cbpy_tab[cbp>>2].len;
2699                            Data->temp[6] = t;
2700    
2701                            bits += t = mcbpc_inter_tab[(MODE_INTRA & 7) | ((cbp & 3) << 3)].len;
2702                            Data->temp[7] = t;
2703    
2704          }          }
2705  }  }
2706    
2707            return bits;
2708    }

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

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