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

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

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