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

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

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