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

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

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