[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 724, Sun Dec 15 14:24:20 2002 UTC
# Line 31  Line 31 
31  #include <assert.h>  #include <assert.h>
32  #include <stdio.h>  #include <stdio.h>
33  #include <stdlib.h>  #include <stdlib.h>
34    #include <string.h>     // memcpy
35    
36  #include "../encoder.h"  #include "../encoder.h"
37  #include "../utils/mbfunctions.h"  #include "../utils/mbfunctions.h"
38  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
39  #include "../global.h"  #include "../global.h"
40  #include "../utils/timer.h"  #include "../utils/timer.h"
41    #include "../image/interpolate8x8.h"
42  #include "motion_est.h"  #include "motion_est.h"
43  #include "motion.h"  #include "motion.h"
44  #include "sad.h"  #include "sad.h"
45    #include "../utils/emms.h"
46    
47  #define INITIAL_SKIP_THRESH     (10)  #define INITIAL_SKIP_THRESH     (10)
48  #define FINAL_SKIP_THRESH       (50)  #define FINAL_SKIP_THRESH       (50)
49  #define MAX_SAD00_FOR_SKIP      (20)  #define MAX_SAD00_FOR_SKIP      (20)
50  #define MAX_CHROMA_SAD_FOR_SKIP (18)  #define MAX_CHROMA_SAD_FOR_SKIP (22)
 #define SKIP_THRESH_B (10)  
51    
52  #define CHECK_CANDIDATE(X,Y,D) { \  #define CHECK_CANDIDATE(X,Y,D) { \
53  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }
54    
 #define iDiamondSize 2  
   
 //FILE * debug;  
   
55  static __inline int  static __inline int
56  d_mv_bits(int x, int y, const uint32_t iFcode)  d_mv_bits(int x, int y, const VECTOR pred, const uint32_t iFcode, const int qpel, const int rrv)
57  {  {
58          int xb, yb;          int xb, yb;
59            if (qpel) { x *= 2; y *= 2;}
60            else if (rrv) { x = RRV_MV_SCALEDOWN(x); y = RRV_MV_SCALEDOWN(y); }
61            x = pred.x - 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            Reference = GetReference(x, y, 0, data);
287            t = d_mv_bits(x, y, data->predMV, data->iFcode, 0, 1);
288    
289          t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          data->temp[0] = sad32v_c(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
290          data->temp[0] += lambda_vec16[data->iQuant] * t;  
291          data->temp[1] += lambda_vec8[data->iQuant] * t;          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 = sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);
334            sad += (data->lambda16 * t * sad)/1000;
335    
336            if (sad < *(data->iMinSAD)) {
337                    *(data->iMinSAD) = sad;
338                    current->x = x; current->y = y;
339                    *dir = Direction; }
340    }
341    
342    static void
343    CheckCandidate16no4vI(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            int32_t sad;
347    
348          sad = lambda_vec16[data->iQuant] *          if (( x > data->max_dx) || ( x < data->min_dx)
349                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);                  || ( y > data->max_dy) || (y < data->min_dy)) return;
350          sad += sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);  
351            sad = sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),
352                                            data->iEdgedWidth, 256*4096);
353    
354          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
355                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 148  Line 357 
357                  *dir = Direction; }                  *dir = Direction; }
358  }  }
359    
360    
361  static void  static void
362  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)
363  {  {
364          int32_t sad;          int32_t sad;
365          const int xb = data->currentMV[1].x;          int xb, yb, t;
         const int yb = data->currentMV[1].y;  
366          const uint8_t *ReferenceF, *ReferenceB;          const uint8_t *ReferenceF, *ReferenceB;
367            VECTOR *current;
368    
369          if (( xf > data->max_dx) || ( xf < data->min_dx)          if (( xf > data->max_dx) || ( xf < data->min_dx)
370                  || ( yf > data->max_dy) || (yf < data->min_dy)) return;                  || ( yf > data->max_dy) || (yf < data->min_dy)) return;
371    
372          switch ( ((xf&1)<<1) + (yf&1) ) {          if (data->qpel_precision) {
373                  case 0 : ReferenceF = data->Ref + xf/2 + (yf/2)*(data->iEdgedWidth); break;                  ReferenceF = Interpolate16x16qpel(xf, yf, 0, data);
374                  case 1 : ReferenceF = data->RefV + xf/2 + ((yf-1)/2)*(data->iEdgedWidth); break;                  xb = data->currentQMV[1].x; yb = data->currentQMV[1].y;
375                  case 2 : ReferenceF = data->RefH + (xf-1)/2 + (yf/2)*(data->iEdgedWidth); break;                  current = data->currentQMV;
376                  default : ReferenceF = data->RefHV + (xf-1)/2 + ((yf-1)/2)*(data->iEdgedWidth); break;                  ReferenceB = Interpolate16x16qpel(xb, yb, 1, data);
377          }          } else {
378                    ReferenceF = GetReference(xf, yf, 0, data);
379          switch ( ((xb&1)<<1) + (yb&1) ) {                  xb = data->currentMV[1].x; yb = data->currentMV[1].y;
380                  case 0 : ReferenceB = data->bRef + xb/2 + (yb/2)*(data->iEdgedWidth); break;                  ReferenceB = GetReference(xb, yb, 1, data);
381                  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;  
382          }          }
383    
384          sad = lambda_vec16[data->iQuant] *          t = d_mv_bits(xf, yf, data->predMV, data->iFcode, data->qpel && !data->qpel_precision, 0)
385                          ( 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) );  
386    
387          sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
388            sad += (data->lambda16 * t * sad)/1000;
389    
390          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
391                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
392                  data->currentMV->x = xf; data->currentMV->y = yf;                  current->x = xf; current->y = yf;
393                  *dir = Direction; }                  *dir = Direction; }
394  }  }
395    
396  static void  static void
397  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)
398  {  {
399          int32_t sad;          int32_t sad = 0;
400          int k;          int k;
401          const uint8_t *ReferenceF;          const uint8_t *ReferenceF;
402          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
403          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
404            const VECTOR zeroMV={0,0};
405    
406          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
407    
         sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);  
   
408          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
409                  mvs.x = data->directmvF[k].x + x;                  mvs.x = data->directmvF[k].x + x;
410                  b_mvs.x = ((x == 0) ?                  b_mvs.x = ((x == 0) ?
# Line 214  Line 421 
421                          || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )                          || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )
422                          || ( 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;
423    
424                  switch ( ((mvs.x&1)<<1) + (mvs.y&1) ) {                  if (!data->qpel) {
425                          case 0 : ReferenceF = data->Ref + mvs.x/2 + (mvs.y/2)*(data->iEdgedWidth); break;                          mvs.x *= 2; mvs.y *= 2;
426                          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;  
427                  }                  }
428                    ReferenceF = Interpolate8x8qpel(mvs.x, mvs.y, k, 0, data);
429                    ReferenceB = Interpolate8x8qpel(b_mvs.x, b_mvs.y, k, 1, data);
430    
431                  sad += sad8bi(data->Cur + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),                  sad += sad8bi(data->Cur + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
432                                                  ReferenceF + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),                                                  ReferenceF, ReferenceB,
                                                 ReferenceB + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),  
433                                                  data->iEdgedWidth);                                                  data->iEdgedWidth);
434                  if (sad > *(data->iMinSAD)) return;                  if (sad > *(data->iMinSAD)) return;
435          }          }
436    
437            sad += (data->lambda16 * d_mv_bits(x, y, zeroMV, 1, 0, 0) * sad)/1000;
438    
439          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
440                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
441                  data->currentMV->x = x; data->currentMV->y = y;                  data->currentMV->x = x; data->currentMV->y = y;
# Line 248  Line 449 
449          const uint8_t *ReferenceF;          const uint8_t *ReferenceF;
450          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
451          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
452            const VECTOR zeroMV = {0,0};
453    
454          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);  
455    
456          mvs.x = data->directmvF[0].x + x;          mvs.x = data->directmvF[0].x + x;
457          b_mvs.x = ((x == 0) ?          b_mvs.x = ((x == 0) ?
# Line 268  Line 468 
468                  || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )                  || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )
469                  || ( 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;
470    
471          switch ( ((mvs.x&1)<<1) + (mvs.y&1) ) {          if (!data->qpel) {
472                  case 0 : ReferenceF = data->Ref + mvs.x/2 + (mvs.y/2)*(data->iEdgedWidth); break;                          mvs.x *= 2; mvs.y *= 2;
473                  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;  
474          }          }
475            ReferenceF = Interpolate16x16qpel(mvs.x, mvs.y, 0, data);
476            ReferenceB = Interpolate16x16qpel(b_mvs.x, b_mvs.y, 1, data);
477    
478          sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
479            sad += (data->lambda16 * d_mv_bits(x, y, zeroMV, 1, 0, 0) * sad)/1000;
480    
481          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
482                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 293  Line 487 
487  static void  static void
488  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)
489  {  {
490          int32_t sad;          int32_t sad; int t;
491          const uint8_t * Reference;          const uint8_t * Reference;
492    
493          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
494                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
495    
496          switch ( ((x&1)<<1) + (y&1) )          if (data->qpel) Reference = Interpolate16x16qpel(x, y, 0, data);
497          {          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;  
         }  
498    
499          sad = sad8(data->Cur, Reference, data->iEdgedWidth);          sad = sad8(data->Cur, Reference, data->iEdgedWidth);
500          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);
501    
502            sad += (data->lambda8 * t * (sad+NEIGH_8X8_BIAS))/100;
503    
504          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
505                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 316  Line 507 
507                  *dir = Direction; }                  *dir = Direction; }
508  }  }
509    
510  /* CHACK_CANDIATE FUNCTIONS END */  /* CHECK_CANDIATE FUNCTIONS END */
511    
512  /* MAINSEARCH FUNCTIONS START */  /* MAINSEARCH FUNCTIONS START */
513    
# Line 328  Line 519 
519    
520                  int iDirection;                  int iDirection;
521    
522                  do {          for(;;) { //forever
523                          iDirection = 0;                          iDirection = 0;
524                          if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);                          if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);
525                          if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);                          if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);
# Line 346  Line 537 
537                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);
538                                  } else {                        // what remains here is up or down                                  } else {                        // what remains here is up or down
539                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);
540                                          CHECK_CANDIDATE(x - iDiamondSize, y, 1); }                                  CHECK_CANDIDATE(x - iDiamondSize, y, 1);
541                            }
542    
543                                  if (iDirection) {                                  if (iDirection) {
544                                          bDirection += iDirection;                                          bDirection += iDirection;
545                                          x = data->currentMV->x; y = data->currentMV->y; }                                  x = data->currentMV->x; y = data->currentMV->y;
546                            }
547                          } else {                                //about to quit, eh? not so fast....                          } else {                                //about to quit, eh? not so fast....
548                                  switch (bDirection) {                                  switch (bDirection) {
549                                  case 2:                                  case 2:
# Line 401  Line 594 
594                                  x = data->currentMV->x; y = data->currentMV->y;                                  x = data->currentMV->x; y = data->currentMV->y;
595                          }                          }
596                  }                  }
                 while (1);                              //forever  
597  }  }
598    
599  static void  static void
# Line 451  Line 643 
643                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);                                          CHECK_CANDIDATE(x, y - iDiamondSize, 4);
644                                  } else {                        // what remains here is up or down                                  } else {                        // what remains here is up or down
645                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);                                          CHECK_CANDIDATE(x + iDiamondSize, y, 2);
646                                          CHECK_CANDIDATE(x - iDiamondSize, y, 1); }                                  CHECK_CANDIDATE(x - iDiamondSize, y, 1);
647                            }
648                                  bDirection += iDirection;                                  bDirection += iDirection;
649                                  x = data->currentMV->x; y = data->currentMV->y;                                  x = data->currentMV->x; y = data->currentMV->y;
650                          }                          }
# Line 465  Line 657 
657  /* 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 */
658    
659  static void  static void
660  HalfpelRefine(const SearchData * const data)  SubpelRefine(const SearchData * const data)
661  {  {
662  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a half-pel or q-pel refinement */
663            VECTOR backupMV;
         VECTOR backupMV = *(data->currentMV);  
664          int iDirection; //not needed          int iDirection; //not needed
665    
666            if (data->qpel_precision)
667                    backupMV = *(data->currentQMV);
668            else backupMV = *(data->currentMV);
669    
670          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);
671          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);
672          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);
# Line 487  Line 682 
682  static __inline int  static __inline int
683  SkipDecisionP(const IMAGE * current, const IMAGE * reference,  SkipDecisionP(const IMAGE * current, const IMAGE * reference,
684                                                          const int x, const int y,                                                          const int x, const int y,
685                                                          const uint32_t iEdgedWidth, const uint32_t iQuant)                                                          const uint32_t iEdgedWidth, const uint32_t iQuant, int rrv)
686    
687  {  {
688  /*      keep repeating checks for all b-frames before this P frame,  /*      keep repeating checks for all b-frames before this P frame,
689          to make sure that SKIP is possible (todo)          to make sure that SKIP is possible (todo)
690          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 */
691            if(rrv) {
692                    uint32_t sadC = sad16(current->u + x*16 + y*(iEdgedWidth/2)*16,
693                                                    reference->u + x*16 + y*(iEdgedWidth/2)*16, iEdgedWidth/2, 256*4096);
694                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP*4) return 0;
695                    sadC += sad16(current->v + (x + y*(iEdgedWidth/2))*16,
696                                                    reference->v + (x + y*(iEdgedWidth/2))*16, iEdgedWidth/2, 256*4096);
697                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP*4) return 0;
698                    return 1;
699            } else {
700          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,
701                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);
702          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
703          sadC += sad8(current->v + x*8 + y*(iEdgedWidth/2)*8,                  sadC += sad8(current->v + (x + y*(iEdgedWidth/2))*8,
704                                          reference->v + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                                  reference->v + (x + y*(iEdgedWidth/2))*8, iEdgedWidth/2);
705          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
   
706          return 1;          return 1;
707  }  }
708    }
709    
710  static __inline void  static __inline void
711  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)
712  {  {
713          pMB->mode = MODE_NOT_CODED;          pMB->mode = MODE_NOT_CODED;
714          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;
715          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;
716    
717            pMB->qmvs[0].x = pMB->qmvs[1].x = pMB->qmvs[2].x = pMB->qmvs[3].x = 0;
718            pMB->qmvs[0].y = pMB->qmvs[1].y = pMB->qmvs[2].y = pMB->qmvs[3].y = 0;
719    
720          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;
721  }  }
722    
# Line 528  Line 735 
735    
736          const VECTOR zeroMV = { 0, 0 };          const VECTOR zeroMV = { 0, 0 };
737    
738            uint32_t mb_width = pParam->mb_width;
739            uint32_t mb_height = pParam->mb_height;
740    
741          uint32_t x, y;          uint32_t x, y;
742          uint32_t iIntra = 0;          uint32_t iIntra = 0;
743          int32_t InterBias;          int32_t InterBias, quant = current->quant, sad00;
744            uint8_t *qimage;
745    
746            // some pre-initialized thingies for SearchP
747            int32_t temp[8];
748            VECTOR currentMV[5];
749            VECTOR currentQMV[5];
750            int32_t iMinSAD[5];
751            SearchData Data;
752            memset(&Data, 0, sizeof(SearchData));
753            Data.iEdgedWidth = pParam->edged_width;
754            Data.currentMV = currentMV;
755            Data.currentQMV = currentQMV;
756            Data.iMinSAD = iMinSAD;
757            Data.temp = temp;
758            Data.iFcode = current->fcode;
759            Data.rounding = pParam->m_rounding_type;
760            Data.qpel = pParam->m_quarterpel;
761            Data.chroma = current->global_flags & XVID_ME_COLOUR;
762            Data.rrv = current->global_flags & XVID_REDUCED;
763    
764            if ((current->global_flags & XVID_REDUCED)) {
765                    mb_width = (pParam->width + 31) / 32;
766                    mb_height = (pParam->height + 31) / 32;
767                    Data.qpel = Data.chroma = 0;
768            }
769    
770            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
771                    return 1; // allocate some mem for qpel interpolated blocks
772                                      // somehow this is dirty since I think we shouldn't use malloc outside
773                                      // encoder_create() - so please fix me!
774            Data.RefQ = qimage;
775          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
776    
777          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < mb_height; y++) {
778                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < mb_width; x++)  {
   
779                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
780                          int32_t sad00 =  pMB->sad16  
781                                  = sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,                          if (Data.rrv) pMB->sad16 =
782                                    sad32v_c(pCurrent->y + (x + y * pParam->edged_width) * 32,
783                                                            pRef->y + (x + y * pParam->edged_width) * 32,
784                                                            pParam->edged_width, pMB->sad8 );
785    
786                            else pMB->sad16 =
787                                    sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,
788                                                          pRef->y + (x + y * pParam->edged_width) * 16,                                                          pRef->y + (x + y * pParam->edged_width) * 16,
789                                                          pParam->edged_width, pMB->sad8 );                                                          pParam->edged_width, pMB->sad8 );
790    
791                            if (Data.chroma) {
792                                    pMB->sad16 += sad8(pCurrent->u + x*8 + y*(pParam->edged_width/2)*8,
793                                                                    pRef->u + x*8 + y*(pParam->edged_width/2)*8, pParam->edged_width/2);
794    
795                                    pMB->sad16 += sad8(pCurrent->v + (x + y*(pParam->edged_width/2))*8,
796                                                                    pRef->v + (x + y*(pParam->edged_width/2))*8, pParam->edged_width/2);
797                            }
798    
799                            sad00 = pMB->sad16; //if no gmc; else sad00 = (..)
800    
801                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
802                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
803                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant;
804                            } else {
805                                    if (pMB->dquant != NO_CHANGE) {
806                                            quant += DQtab[pMB->dquant];
807                                            if (quant > 31) quant = 31;
808                                            else if (quant < 1) quant = 1;
809                                    }
810                                    pMB->quant = quant;
811                            }
812    
813  //initial skip decision  //initial skip decision
814    /* no early skip for GMC (global vector = skip vector is unknown!)  */
815                          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 */
816                                  && (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) )
817                                  if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {                                          if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant, Data.rrv)) {
818                                                  SkipMacroblockP(pMB, sad00);                                                  SkipMacroblockP(pMB, sad00);
819                                                  continue;                                                  continue;
820                                  }                                  }
821                          } else sad00 = 256*4096; // skip not allowed - for final skip decision                          }
822    
823                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchP(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
824                                                  y, current->motion_flags, pMB->quant,                                                  y, current->motion_flags, pMB->quant,
825                                                  current->fcode, pParam, pMBs, reference->mbs,                                                  &Data, pParam, pMBs, reference->mbs,
826                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
827    
828  /* 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?" */
829                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)                          if (current->coding_type == P_VOP)      {
830                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)                                  if ( (pMB->dquant == NO_CHANGE) && (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)
831                                  { SkipMacroblockP(pMB, sad00); continue; }                                          && ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH * (Data.rrv ? 4:1)) )
832                                            if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant, Data.rrv)) {
833                                                    SkipMacroblockP(pMB, sad00);
834                                                    continue;
835                                            }
836                            }
837    
838  /* finally, intra decision */  /* finally, intra decision */
839    
840                          InterBias = MV16_INTER_BIAS;                          InterBias = MV16_INTER_BIAS;
841                          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
842                          if (y != 0)                          if (y != 0)
843                                  if ((pMB - pParam->mb_width)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - pParam->mb_width)->mode == MODE_INTRA ) InterBias -= 80;
844                          if (x != 0)                          if (x != 0)
845                                  if ((pMB - 1)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - 1)->mode == MODE_INTRA ) InterBias -= 80;
846    
847                            if (Data.chroma) InterBias += 50; // to compensate bigger SAD
848                            if (Data.rrv) InterBias *= 4; //??
849    
850                          if (InterBias < pMB->sad16)  {                          if (InterBias < pMB->sad16)  {
851                                  const int32_t deviation =                                  int32_t deviation;
852                                          dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                  if (Data.rrv) {
853                                            deviation = dev16(pCurrent->y + (x + y * pParam->edged_width) * 32,
854                                                                                    pParam->edged_width)
855                                                    + dev16(pCurrent->y + (x + y * pParam->edged_width) * 32 + 16,
856                                                                                    pParam->edged_width)
857                                                    + dev16(pCurrent->y + (x + y * pParam->edged_width) * 32 + 16 * pParam->edged_width,
858                                                                                    pParam->edged_width)
859                                                    + dev16(pCurrent->y + (x + y * pParam->edged_width) * 32 + 16 * (pParam->edged_width+1),
860                                                                                    pParam->edged_width);
861                                    } else
862                                            deviation = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
863                                                    pParam->edged_width);                                                    pParam->edged_width);
864    
865                                  if (deviation < (pMB->sad16 - InterBias)) {                                  if (deviation < (pMB->sad16 - InterBias)) {
866                                          if (++iIntra >= iLimit) return 1;                                          if (++iIntra >= iLimit) { free(qimage); return 1; }
867                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
868                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
869                                                  pMB->mvs[3] = zeroMV;                                                  pMB->mvs[3] = zeroMV;
870                                            pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] =
871                                                            pMB->qmvs[3] = zeroMV;
872                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
873                                                  pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
874                                  }                                  }
875                          }                          }
876                  }                  }
877          }          }
878            free(qimage);
879    
880            if (current->coding_type == S_VOP)      /* first GMC step only for S(GMC)-VOPs */
881                    current->GMC_MV = GlobalMotionEst( pMBs, pParam, current->fcode );
882            else
883                    current->GMC_MV = zeroMV;
884    
885          return 0;          return 0;
886  }  }
887    
# Line 601  Line 891 
891  static __inline int  static __inline int
892  make_mask(const VECTOR * const pmv, const int i)  make_mask(const VECTOR * const pmv, const int i)
893  {  {
894          int mask = 0xFF, j;          int mask = 255, j;
895          for (j = 0; j < i; j++) {          for (j = 0; j < i; j++) {
896                  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
897                  if (pmv[i].x == pmv[j].x) {                  if (pmv[i].x == pmv[j].x) {
# Line 617  Line 907 
907  }  }
908    
909  static __inline void  static __inline void
910  PreparePredictionsP(VECTOR * const pmv, int x, int y, const int iWcount,  PreparePredictionsP(VECTOR * const pmv, int x, int y, int iWcount,
911                          const int iHcount, const MACROBLOCK * const prevMB)                          int iHcount, const MACROBLOCK * const prevMB, int rrv)
912  {  {
913    
914  //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
915            if (rrv) { iWcount /= 2; iHcount /= 2; }
916    
917          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour          if ( (y != 0) && (x < (iWcount-1)) ) {          // [5] top-right neighbour
918                  pmv[5].x = EVEN(pmv[3].x);                  pmv[5].x = EVEN(pmv[3].x);
919                  pmv[5].y = EVEN(pmv[3].y); }                  pmv[5].y = EVEN(pmv[3].y);
920          else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
921    
922          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
923          else pmv[3].x = pmv[3].y = 0;          else pmv[3].x = pmv[3].y = 0;
# Line 635  Line 926 
926      else pmv[4].x = pmv[4].y = 0;      else pmv[4].x = pmv[4].y = 0;
927    
928          // [1] median prediction          // [1] median prediction
929          pmv[1].x = EVEN(pmv[0].x); pmv[1].y = EVEN(pmv[0].y);          if (rrv) { //median is in halfzero-precision
930                    pmv[1].x = RRV_MV_SCALEUP(pmv[0].x);
931                    pmv[1].y = RRV_MV_SCALEUP(pmv[0].y);
932            } else { pmv[1].x = EVEN(pmv[0].x); pmv[1].y = EVEN(pmv[0].y); }
933    
934          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
935    
936          pmv[2].x = EVEN(prevMB->mvs[0].x); // [2] is last frame          pmv[2].x = EVEN(prevMB->mvs[0].x); // [2] is last frame
937          pmv[2].y = EVEN(prevMB->mvs[0].y);          pmv[2].y = EVEN(prevMB->mvs[0].y);
938    
939          if ((x != iWcount-1) && (y != iHcount-1)) {          if ((x < iWcount-1) && (y < iHcount-1)) {
940                  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
941                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y); }                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
942          else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
943    
944            if (rrv) {
945                    int i;
946                    for (i = 0; i < 7; i++) {
947                            pmv[i].x = RRV_MV_SCALEDOWN(pmv[i].x);
948                            pmv[i].x = RRV_MV_SCALEUP(pmv[i].x); // a trick
949                    }
950            }
951  }  }
952    
953  static void  static void
954  SearchP(const uint8_t * const pRef,  SearchP(const IMAGE * const pRef,
955                  const uint8_t * const pRefH,                  const uint8_t * const pRefH,
956                  const uint8_t * const pRefV,                  const uint8_t * const pRefV,
957                  const uint8_t * const pRefHV,                  const uint8_t * const pRefHV,
# Line 658  Line 960 
960                  const int y,                  const int y,
961                  const uint32_t MotionFlags,                  const uint32_t MotionFlags,
962                  const uint32_t iQuant,                  const uint32_t iQuant,
963                  const uint32_t iFcode,                  SearchData * const Data,
964                  const MBParam * const pParam,                  const MBParam * const pParam,
965                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
966                  const MACROBLOCK * const prevMBs,                  const MACROBLOCK * const prevMBs,
# Line 666  Line 968 
968                  MACROBLOCK * const pMB)                  MACROBLOCK * const pMB)
969  {  {
970    
         const int32_t iEdgedWidth = pParam->edged_width;  
   
971          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
972          int32_t temp[5];          VECTOR pmv[7];
         VECTOR currentMV[5], pmv[7];  
         int32_t psad[4], iMinSAD[5];  
         MainSearchFunc * MainSearchPtr;  
         SearchData Data;  
973    
974          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,
975          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;  
976    
977          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;  
978    
979          if (!(MotionFlags & PMV_HALFPEL16)) {          Data->temp[5] = Data->temp[7] = 256*4096; // to reset chroma-sad cache
980                  Data.min_dx = EVEN(Data.min_dx);          if (Data->rrv) i = 2; else i = 1;
981                  Data.max_dx = EVEN(Data.max_dx);          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16*i;
982                  Data.min_dy = EVEN(Data.min_dy);          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
983                  Data.max_dy = EVEN(Data.max_dy); }          Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
984    
985          for(i = 0;  i < 5; i++) currentMV[i].x = currentMV[i].y = 0;          Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16*i;
986            Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16*i;
987          i = d_mv_bits(pmv[0].x, pmv[0].y, iFcode);          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16*i;
988            Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16*i;
989          iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;          Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
990          iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;          Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
991          iMinSAD[2] = pMB->sad8[1];  
992          iMinSAD[3] = pMB->sad8[2];          Data->lambda16 = lambda_vec16[iQuant];
993          iMinSAD[4] = pMB->sad8[3];          Data->lambda8 = lambda_vec8[iQuant];
994            Data->qpel_precision = 0;
995    
996          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
997    
998            for(i = 0;  i < 5; i++)
999                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
1000    
1001            if (pParam->m_quarterpel) Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1002            else Data->predMV = pmv[0];
1003    
1004            i = d_mv_bits(0, 0, Data->predMV, Data->iFcode, 0, 0);
1005            Data->iMinSAD[0] = pMB->sad16 + (Data->lambda16 * i * pMB->sad16)/1000;
1006            Data->iMinSAD[1] = pMB->sad8[0] + (Data->lambda8 * i * (pMB->sad8[0]+NEIGH_8X8_BIAS))/100;
1007            Data->iMinSAD[2] = pMB->sad8[1];
1008            Data->iMinSAD[3] = pMB->sad8[2];
1009            Data->iMinSAD[4] = pMB->sad8[3];
1010    
1011          if ((x == 0) && (y == 0)) threshA = 512;          if ((x == 0) && (y == 0)) threshA = 512;
1012          else {          else {
1013                  threshA = psad[0] + 20;                  threshA = Data->temp[0]; // that's when we keep this SAD atm
1014                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
1015                  if (threshA > 1024) threshA = 1024; }                  if (threshA > 1024) threshA = 1024; }
1016    
1017          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,
1018                                          prevMBs + x + y * pParam->mb_width);                                          prevMBs + x + y * pParam->mb_width, Data->rrv);
1019    
1020          if (inter4v) CheckCandidate = CheckCandidate16;          if (Data->rrv) CheckCandidate = CheckCandidate32;
1021          else CheckCandidate = CheckCandidate16no4v;          else if (inter4v || Data->chroma) CheckCandidate = CheckCandidate16;
1022                    else CheckCandidate = CheckCandidate16no4v; //for extra speed
1023    
1024  /* main loop. checking all predictions */  /* main loop. checking all predictions */
1025    
1026          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
1027                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1028                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  (*CheckCandidate)(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1029                  if (iMinSAD[0] < threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1030          }          }
1031    
1032          if ((iMinSAD[0] <= threshA) ||          if ((Data->iMinSAD[0] <= threshA) ||
1033                          (MVequal(currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
1034                          (iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {                          (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {
1035                  inter4v = 0;                  inter4v = 0;
1036                  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;  
                 }  
         }  
1037    
1038          if (MotionFlags & PMV_USESQUARES16)                  MainSearchFunc * MainSearchPtr;
1039                  MainSearchPtr = SquareSearch;                  if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
1040          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
                 MainSearchPtr = AdvDiamondSearch;  
1041                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1042    
1043          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, iDirection);                  (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1044    
1045  /* extended search, diamond starting in 0,0 and in prediction.  /* extended search, diamond starting in 0,0 and in prediction.
1046          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 1048 
1048    
1049          if (MotionFlags & PMV_EXTSEARCH16) {          if (MotionFlags & PMV_EXTSEARCH16) {
1050                  int32_t bSAD;                  int32_t bSAD;
1051                  VECTOR startMV = Data.predMV, backupMV = currentMV[0];                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
1052                            if (Data->rrv) {
1053                                    startMV.x = RRV_MV_SCALEUP(startMV.x);
1054                                    startMV.y = RRV_MV_SCALEUP(startMV.y);
1055                            } else
1056                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?
1057                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);
1058                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1059                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1060    
1061                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1062                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1063                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1064                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1065                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1066                  }                  }
1067    
1068                  backupMV = currentMV[0];                          backupMV = Data->currentMV[0];
1069                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;                          if (!MotionFlags & PMV_HALFPELREFINE16 || Data->rrv) startMV.x = startMV.y = 0;
1070                  else startMV.x = startMV.y = 0;                          else startMV.x = startMV.y = 1;
1071                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1072                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1073    
1074                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1075                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1076                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1077                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1078                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1079                            }
1080                  }                  }
1081          }          }
1082    
1083  PMVfast16_Terminate_with_Refine:          if (MotionFlags & PMV_HALFPELREFINE16) SubpelRefine(Data);
1084    
1085            for(i = 0; i < 5; i++) {
1086                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1087                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1088            }
1089    
1090          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if((!Data->rrv) && (pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1091    
1092                    Data->qpel_precision = 1;
1093                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1094                                    pParam->width, pParam->height, Data->iFcode, 1, 0);
1095    
1096                    SubpelRefine(Data);
1097            }
1098    
1099  PMVfast16_Terminate_without_Refine:          if (Data->iMinSAD[0] < (int32_t)iQuant * 30 ) inter4v = 0;
1100            if (inter4v) {
1101                    SearchData Data8;
1102                    Data8.iFcode = Data->iFcode;
1103                    Data8.lambda8 = Data->lambda8;
1104                    Data8.iEdgedWidth = Data->iEdgedWidth;
1105                    Data8.RefQ = Data->RefQ;
1106                    Data8.qpel = Data->qpel;
1107                    Data8.rrv = Data->rrv;
1108                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1109                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1110                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1111                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1112    
1113          if (inter4v)                  if (Data->chroma) {
1114                  for(i = 0; i < 4; i++)                          int sumx, sumy, dx, dy;
1115                          Search8(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);  
1116                            if(pParam->m_quarterpel) {
1117                                    sumx= pMB->qmvs[0].x/2 + pMB->qmvs[1].x/2 + pMB->qmvs[2].x/2 + pMB->qmvs[3].x/2;
1118                                    sumy = pMB->qmvs[0].y/2 + pMB->qmvs[1].y/2 + pMB->qmvs[2].y/2 + pMB->qmvs[3].y/2;
1119                            } else {
1120                                    sumx = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1121                                    sumy = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1122                            }
1123                            dx = (sumx >> 3) + roundtab_76[sumx & 0xf];
1124                            dy = (sumy >> 3) + roundtab_76[sumy & 0xf];
1125    
1126                            Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);
1127                    }
1128            }
1129    
1130            if (Data->rrv) {
1131                            Data->currentMV[0].x = RRV_MV_SCALEDOWN(Data->currentMV[0].x);
1132                            Data->currentMV[0].y = RRV_MV_SCALEDOWN(Data->currentMV[0].y);
1133            }
1134          if (!(inter4v) ||          if (!(inter4v) ||
1135                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
1136                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1137  // INTER MODE  // INTER MODE
1138                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1139                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1140                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1141    
1142                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1143                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1144    
1145                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1146                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->qmvs[0] = pMB->qmvs[1]
1147                                    = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1148                            pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predMV.x;
1149                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predMV.y;
1150                    } else {
1151                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1152                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1153                    }
1154          } else {          } else {
1155  // INTER4V MODE; all other things are already set in Search8  // INTER4V MODE; all other things are already set in Search8
1156                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1157                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1158                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1159          }          }
   
1160  }  }
1161    
1162  static void  static void
# Line 820  Line 1166 
1166                  const MBParam * const pParam,                  const MBParam * const pParam,
1167                  MACROBLOCK * const pMB,                  MACROBLOCK * const pMB,
1168                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
1169                  const int block)                  const int block,
1170                    SearchData * const Data)
1171  {  {
1172          SearchData Data;          int i = 0;
1173            Data->iMinSAD = OldData->iMinSAD + 1 + block;
1174            Data->currentMV = OldData->currentMV + 1 + block;
1175            Data->currentQMV = OldData->currentQMV + 1 + block;
1176    
1177            if(pParam->m_quarterpel) {
1178                    Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2, y/2, block);
1179                    if (block != 0) i = d_mv_bits(  Data->currentQMV->x, Data->currentQMV->y,
1180                                                                                    Data->predMV, Data->iFcode, 0, 0);
1181    
1182          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          } else {
1183          Data.iMinSAD = OldData->iMinSAD + 1 + block;                  Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2, y/2, block);
1184          Data.currentMV = OldData->currentMV+1+block;                  if (block != 0) {
1185          Data.iFcode = OldData->iFcode;                          if (block != 0) i = d_mv_bits(  Data->currentMV->x, Data->currentMV->y,
1186          Data.iQuant = OldData->iQuant;                                                                                          Data->predMV, Data->iFcode, 0, Data->rrv);
1187                    }
1188          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);  
1189    
1190            *(Data->iMinSAD) += (Data->lambda8 * i * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
1191    
1192          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
1193                    if (Data->rrv) i = 2; else i = 1;
1194    
1195                  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));
1196                  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));
1197                  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));
1198                  Data.RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefHV = OldData->RefHV + i*8 * ((block&1) + pParam->edged_width*(block>>1));
   
                 Data.iEdgedWidth = pParam->edged_width;  
1199    
1200                  Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Cur = OldData->Cur + i*8 * ((block&1) + pParam->edged_width*(block>>1));
1201                    Data->qpel_precision = 0;
1202    
1203                  get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1204                                  pParam->width, pParam->height, OldData->iFcode);                                          pParam->width, pParam->height, OldData->iFcode - Data->qpel, 0, Data->rrv);
1205    
1206                  CheckCandidate = CheckCandidate8;                  if (Data->rrv) CheckCandidate = CheckCandidate16no4v;
1207                    else CheckCandidate = CheckCandidate8;
1208    
1209                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & PMV_EXTSEARCH8) {
1210                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1211    
1212                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1213                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1214                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1215                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1216    
1217                          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);     }                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1218    
1219                            if(*(Data->iMinSAD) < temp_sad) {
1220                                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1221                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1222                            }
1223                    }
1224    
1225                    if (MotionFlags & PMV_HALFPELREFINE8) {
1226                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1227    
1228                            SubpelRefine(Data); // perform halfpel refine of current best vector
1229    
1230                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);                          if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1231                                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1232                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1233                            }
1234                    }
1235    
1236                    if(!Data->rrv && Data->qpel) {
1237                            if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1238                                    (MotionFlags & PMV_QUARTERPELREFINE8)) {
1239                            Data->qpel_precision = 1;
1240                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1241                                    pParam->width, pParam->height, OldData->iFcode, 1, 0);
1242                            SubpelRefine(Data);
1243                            }
1244                    }
1245          }          }
1246    
1247          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;          if (Data->rrv) {
1248          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;                          Data->currentMV->x = RRV_MV_SCALEDOWN(Data->currentMV->x);
1249          pMB->mvs[block] = *(Data.currentMV);                          Data->currentMV->y = RRV_MV_SCALEDOWN(Data->currentMV->y);
1250          pMB->sad8[block] =  4 * (*(Data.iMinSAD));          }
1251    
1252            if(Data->qpel) {
1253                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predMV.x;
1254                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predMV.y;
1255                    pMB->qmvs[block] = *(Data->currentQMV);
1256            } else {
1257                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1258                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1259            }
1260    
1261            pMB->mvs[block] = *(Data->currentMV);
1262            pMB->sad8[block] =  4 * (*Data->iMinSAD);
1263  }  }
1264    
1265  /* B-frames code starts here */  /* B-frames code starts here */
# Line 896  Line 1287 
1287          pmv[2] = ChoosePred(pMB, mode_curr);          pmv[2] = ChoosePred(pMB, mode_curr);
1288          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);
1289    
         pmv[3].x = pmv[3].y = 0;  
1290          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour
1291                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);
1292                  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);
1293            } else pmv[3].x = pmv[3].y = 0;
1294    
1295          if (y != 0) {          if (y != 0) {
1296                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);
# Line 929  Line 1320 
1320                          const IMAGE * const pCur,                          const IMAGE * const pCur,
1321                          const int x, const int y,                          const int x, const int y,
1322                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
1323                          const uint32_t iFcode,                          const uint32_t iFcode,
1324                          const MBParam * const pParam,                          const MBParam * const pParam,
1325                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
1326                          const VECTOR * const predMV,                          const VECTOR * const predMV,
1327                          int32_t * const best_sad,                          int32_t * const best_sad,
1328                          const int32_t mode_current)                          const int32_t mode_current,
1329                            SearchData * const Data)
1330  {  {
1331    
1332          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1333    
1334          int i, iDirection, mask;          int i, iDirection, mask;
1335          VECTOR currentMV, pmv[7];          VECTOR pmv[7];
1336          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1337          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
1338          SearchData Data;          Data->iFcode = iFcode;
1339            Data->qpel_precision = 0;
1340    
1341          Data.iMinSAD = &iMinSAD;          Data->Ref = pRef + (x + y * iEdgedWidth) * 16;
1342          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->RefH = pRefH + (x + y * iEdgedWidth) * 16;
1343          Data.iEdgedWidth = iEdgedWidth;          Data->RefV = pRefV + (x + y * iEdgedWidth) * 16;
1344          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);  
1345    
1346          currentMV.x = currentMV.y = 0;          Data->predMV = *predMV;
1347    
1348            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1349                                    pParam->width, pParam->height, iFcode - Data->qpel, 0, 0);
1350    
1351            pmv[0] = Data->predMV;
1352            if (Data->qpel) { pmv[0].x /= 2; pmv[0].y /= 2; }
1353            PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
1354    
1355            Data->currentMV->x = Data->currentMV->y = 0;
1356          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1357    
1358  // main loop. checking all predictions  // main loop. checking all predictions
1359          for (i = 0; i < 8; i++) {          for (i = 0; i < 8; i++) {
1360                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1361                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1362          }          }
1363    
1364          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 990  Line 1367 
1367                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1368                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1369    
1370          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1371    
1372            SubpelRefine(Data);
1373    
1374          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (Data->qpel) {
1375                    Data->currentQMV->x = 2*Data->currentMV->x;
1376                    Data->currentQMV->y = 2*Data->currentMV->y;
1377                    Data->qpel_precision = 1;
1378                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1379                                            pParam->width, pParam->height, iFcode, 1, 0);
1380                    SubpelRefine(Data);
1381            }
1382    
1383  // three bits are needed to code backward mode. four for forward  // three bits are needed to code backward mode. four for forward
1384  // we treat the bits just like they were vector's  // we treat the bits just like they were vector's
1385          if (mode_current == MODE_FORWARD) iMinSAD +=  4 * lambda_vec16[iQuant];          if (mode_current == MODE_FORWARD) *Data->iMinSAD +=  4 * Data->lambda16;
1386          else iMinSAD +=  3 * lambda_vec16[iQuant];          else *Data->iMinSAD +=  3 * Data->lambda16;
   
1387    
1388          if (iMinSAD < *best_sad) {          if (*Data->iMinSAD < *best_sad) {
1389                  *best_sad = iMinSAD;                  *best_sad = *Data->iMinSAD;
1390                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1391                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  if (Data->qpel) {
1392                  pMB->pmvs[0].y = currentMV.y - predMV->y;                          pMB->pmvs[0].x = Data->currentQMV->x - predMV->x;
1393                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                          pMB->pmvs[0].y = Data->currentQMV->y - predMV->y;
1394                  else pMB->b_mvs[0] = currentMV;                          if (mode_current == MODE_FORWARD)
1395                                    pMB->qmvs[0] = *Data->currentQMV;
1396                            else
1397                                    pMB->b_qmvs[0] = *Data->currentQMV;
1398                    } else {
1399                            pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1400                            pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1401          }          }
1402                    if (mode_current == MODE_FORWARD)
1403                            pMB->mvs[0] = *(Data->currentMV+2) = *Data->currentMV;
1404                    else
1405                            pMB->b_mvs[0] = *(Data->currentMV+1) = *Data->currentMV; //we store currmv for interpolate search
1406    
1407  }  }
1408    
1409  static int32_t  }
1410  SearchDirect(const uint8_t * const f_Ref,  
1411    static void
1412    SkipDecisionB(const IMAGE * const pCur,
1413                              const IMAGE * const f_Ref,
1414                              const IMAGE * const b_Ref,
1415                              MACROBLOCK * const pMB,
1416                              const uint32_t quant,
1417                              const uint32_t x, const uint32_t y,
1418                              const SearchData * const Data)
1419    {
1420            int dx, dy, b_dx, b_dy;
1421            uint32_t sum;
1422    //this is not full chroma compensation, only it's fullpel approximation. should work though
1423            if (Data->qpel) {
1424                    dy = Data->directmvF[0].y/2 + Data->directmvF[1].y/2 +
1425                                    Data->directmvF[2].y/2 + Data->directmvF[3].y/2;
1426    
1427                    dx = Data->directmvF[0].x/2 + Data->directmvF[1].x/2 +
1428                                    Data->directmvF[2].x/2 + Data->directmvF[3].x/2;
1429    
1430                    b_dy = Data->directmvB[0].y/2 + Data->directmvB[1].y/2 +
1431                                    Data->directmvB[2].y/2 + Data->directmvB[3].y/2;
1432    
1433                    b_dx = Data->directmvB[0].x/2 + Data->directmvB[1].x/2 +
1434                                    Data->directmvB[2].x/2 + Data->directmvB[3].x/2;
1435    
1436            } else {
1437                    dy = Data->directmvF[0].y + Data->directmvF[1].y +
1438                                    Data->directmvF[2].y + Data->directmvF[3].y;
1439    
1440                    dx = Data->directmvF[0].x + Data->directmvF[1].x +
1441                                    Data->directmvF[2].x + Data->directmvF[3].x;
1442    
1443                    b_dy = Data->directmvB[0].y + Data->directmvB[1].y +
1444                                    Data->directmvB[2].y + Data->directmvB[3].y;
1445    
1446                    b_dx = Data->directmvB[0].x + Data->directmvB[1].x +
1447                                    Data->directmvB[2].x + Data->directmvB[3].x;
1448            }
1449    
1450    
1451            dy = (dy >> 3) + roundtab_76[dy & 0xf];
1452            dx = (dx >> 3) + roundtab_76[dx & 0xf];
1453            b_dy = (b_dy >> 3) + roundtab_76[b_dy & 0xf];
1454            b_dx = (b_dx >> 3) + roundtab_76[b_dx & 0xf];
1455    
1456            sum = sad8bi(pCur->u + 8*x + 8*y*(Data->iEdgedWidth/2),
1457                                            f_Ref->u + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1458                                            b_Ref->u + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1459                                            Data->iEdgedWidth/2);
1460            sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1461                                            f_Ref->v + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1462                                            b_Ref->v + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1463                                            Data->iEdgedWidth/2);
1464    
1465            if (sum < 2*MAX_CHROMA_SAD_FOR_SKIP * quant) pMB->mode = MODE_DIRECT_NONE_MV; //skipped
1466    }
1467    
1468    
1469    
1470    static __inline uint32_t
1471    SearchDirect(const IMAGE * const f_Ref,
1472                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1473                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
1474                                  const uint8_t * const f_RefHV,                                  const uint8_t * const f_RefHV,
1475                                  const uint8_t * const b_Ref,                                  const IMAGE * const b_Ref,
1476                                  const uint8_t * const b_RefH,                                  const uint8_t * const b_RefH,
1477                                  const uint8_t * const b_RefV,                                  const uint8_t * const b_RefV,
1478                                  const uint8_t * const b_RefHV,                                  const uint8_t * const b_RefHV,
1479                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1480                                  const int x, const int y,                                  const int x, const int y,
1481                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1482                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1483                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1484                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1485                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1486                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1487                                    SearchData * const Data)
1488    
1489  {  {
1490          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
         int32_t iMinSAD = 0, skip_sad;  
1491          int k;          int k;
1492          VECTOR currentMV;  
1493          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
         SearchData Data;  
1494    
1495          Data.iMinSAD = &iMinSAD;          *Data->iMinSAD = 256*4096;
         Data.Cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;  
         Data.iEdgedWidth = iEdgedWidth;  
         Data.currentMV = &currentMV;  
         Data.iQuant = iQuant;  
         Data.referencemv = b_mb->mvs;  
1496    
1497          Data.Ref= f_Ref + (x + iEdgedWidth*y) * 16;          Data->Ref = f_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1498          Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;          Data->RefH = f_RefH + (x + Data->iEdgedWidth*y) * 16;
1499          Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;          Data->RefV = f_RefV + (x + Data->iEdgedWidth*y) * 16;
1500          Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = f_RefHV + (x + Data->iEdgedWidth*y) * 16;
1501          Data.bRef = b_Ref + (x + iEdgedWidth*y) * 16;          Data->bRef = b_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1502          Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;          Data->bRefH = b_RefH + (x + Data->iEdgedWidth*y) * 16;
1503          Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;          Data->bRefV = b_RefV + (x + Data->iEdgedWidth*y) * 16;
1504          Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;          Data->bRefHV = b_RefHV + (x + Data->iEdgedWidth*y) * 16;
1505  /*  
1506  //What we do here is a complicated version of CheckCandidateDirect(0,0);          Data->max_dx = 2 * pParam->width - 2 * (x) * 16;
1507  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 * pParam->height - 2 * (y) * 16;
1508            Data->min_dx = -(2 * 16 + 2 * (x) * 16);
1509  */          Data->min_dy = -(2 * 16 + 2 * (y) * 16);
1510          Data.max_dx = 2 * pParam->width - 2 * (x) * 16;          if (Data->qpel) { //we measure in qpixels
1511          Data.max_dy = 2 * pParam->height - 2 * (y) * 16;                  Data->max_dx *= 2;
1512          Data.min_dx = -(2 * 16 + 2 * (x) * 16);                  Data->max_dy *= 2;
1513          Data.min_dy = -(2 * 16 + 2 * (y) * 16);                  Data->min_dx *= 2;
1514                    Data->min_dy *= 2;
1515                    Data->referencemv = b_mb->qmvs;
1516            } else Data->referencemv = b_mb->mvs;
1517            Data->qpel_precision = 0; // it's a trick. it's 1 not 0, but we need 0 here
1518    
1519          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1520                  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);
1521                  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;
1522                  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);
1523                  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;
1524    
1525          if (( pMB->mvs[k].x > Data.max_dx ) || ( pMB->mvs[k].x < Data.min_dx )                  if ( ( pMB->b_mvs[k].x > Data->max_dx ) || ( pMB->b_mvs[k].x < Data->min_dx )
1526                          || ( pMB->mvs[k].y > Data.max_dy ) || ( pMB->mvs[k].y < Data.min_dy )                          || ( pMB->b_mvs[k].y > Data->max_dy ) || ( pMB->b_mvs[k].y < Data->min_dy )) {
1527                          || ( 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);  
 */  
1528                  *best_sad = 256*4096; // in that case, we won't use direct mode                  *best_sad = 256*4096; // in that case, we won't use direct mode
1529                  pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"                  pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
1530                  pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;  /* because backwards and interpol might rely on this */                          pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;
1531                  return 0; }                          return 256*4096;
1532                    }
1533                    if (b_mb->mode != MODE_INTER4V) {
1534                            pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1535                            pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];
1536                            Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1537                            Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1538                            break;
1539                    }
1540            }
1541    
1542    
1543          if (b_mb->mode != MODE_INTER4V) {          if (b_mb->mode == MODE_INTER4V) CheckCandidate = CheckCandidateDirect;
                 iMinSAD = sad16bi(Data.Cur,  
                                                 get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,  
                                                                 x, y, 16, &pMB->mvs[0], iEdgedWidth),  
                                                 get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,  
                                                                 x, y, 16, &pMB->b_mvs[0], iEdgedWidth), iEdgedWidth);  
   
                 Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];  
                 Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];  
                 break;  
         }  
         iMinSAD += sad8bi(Data.Cur + (k&1)*8 + (k>>1)* 8 * iEdgedWidth,  
                                                 get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,  
                                                                 (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->mvs[k], iEdgedWidth),  
                                                 get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,  
                                                                 (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->b_mvs[k], iEdgedWidth),  
                                                 iEdgedWidth);  
         }  
   
 // 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;  
1544          else CheckCandidate = CheckCandidateDirectno4v;          else CheckCandidate = CheckCandidateDirectno4v;
1545    
1546            (*CheckCandidate)(0, 0, 255, &k, Data);
1547    
1548    // initial (fast) skip decision
1549            if (*Data->iMinSAD < pMB->quant * INITIAL_SKIP_THRESH*2) {
1550                    SkipDecisionB(pCur, f_Ref, b_Ref, pMB, x, y, Data->chroma, Data); //possible skip - checking chroma
1551                    if (pMB->mode == MODE_DIRECT_NONE_MV) return *Data->iMinSAD; // skip.
1552            }
1553    
1554            skip_sad = *Data->iMinSAD;
1555    
1556  //  DIRECT MODE DELTA VECTOR SEARCH.  //  DIRECT MODE DELTA VECTOR SEARCH.
1557  //      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
1558    
# Line 1123  Line 1560 
1560                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1561                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1562    
1563          (*MainSearchPtr)(0, 0, &Data, 255);          (*MainSearchPtr)(0, 0, Data, 255);
1564    
1565          HalfpelRefine(&Data);          SubpelRefine(Data);
1566    
1567          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;  
1568    
1569          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1570                  pMB->mode = MODE_DIRECT;                  pMB->mode = MODE_DIRECT;
1571          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1572    
1573          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1574    
1575          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1576                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1577                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = (     (Data->currentMV->x == 0)
1578                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1579                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          :pMB->mvs[k].x - Data->referencemv[k].x);
1580                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1581                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1582                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1583                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1584                    if (Data->qpel) {
1585                            pMB->qmvs[k].x = pMB->mvs[k].x; pMB->mvs[k].x /= 2;
1586                            pMB->b_qmvs[k].x = pMB->b_mvs[k].x; pMB->b_mvs[k].x /= 2;
1587                            pMB->qmvs[k].y = pMB->mvs[k].y; pMB->mvs[k].y /= 2;
1588                            pMB->b_qmvs[k].y = pMB->b_mvs[k].y; pMB->b_mvs[k].y /= 2;
1589                    }
1590    
1591                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1592                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1593                          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];
1594                            pMB->qmvs[3] = pMB->qmvs[2] = pMB->qmvs[1] = pMB->qmvs[0];
1595                            pMB->b_qmvs[3] = pMB->b_qmvs[2] = pMB->b_qmvs[1] = pMB->b_qmvs[0];
1596                          break;                          break;
1597                  }                  }
1598          }          }
1599          return 0;//skip_sad;          return skip_sad;
1600  }  }
1601    
1602  static __inline void  
1603    static void
1604  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const uint8_t * const f_Ref,
1605                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1606                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
# Line 1168  Line 1614 
1614                                  const uint32_t fcode,                                  const uint32_t fcode,
1615                                  const uint32_t bcode,                                  const uint32_t bcode,
1616                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1617                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1618                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1619                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1620                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1621                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1622                                    SearchData * const fData)
1623    
1624  {  {
 /* 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;  
1625    
1626          int iDirection, i, j;          int iDirection, i, j;
1627          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;  
1628    
1629            fData->qpel_precision = 0;
1630            memcpy(&bData, fData, sizeof(SearchData)); //quick copy of common data
1631            *fData->iMinSAD = 4096*256;
1632            bData.currentMV ++; bData.currentQMV ++;
1633            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1634    
1635            i = (x + y * fData->iEdgedWidth) * 16;
1636            bData.bRef = fData->Ref = f_Ref + i;
1637            bData.bRefH = fData->RefH = f_RefH + i;
1638            bData.bRefV = fData->RefV = f_RefV + i;
1639            bData.bRefHV = fData->RefHV = f_RefHV + i;
1640            bData.Ref = fData->bRef = b_Ref + i;
1641            bData.RefH = fData->bRefH = b_RefH + i;
1642            bData.RefV = fData->bRefV = b_RefV + i;
1643            bData.RefHV = fData->bRefHV = b_RefHV + i;
1644    
1645            bData.bpredMV = fData->predMV = *f_predMV;
1646            fData->bpredMV = bData.predMV = *b_predMV;
1647            fData->currentMV[0] = fData->currentMV[2];
1648    
1649            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);
1650            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);
1651    
1652            if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1653            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dx;
1654            if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dy;
1655            if (fData->currentMV[0].y < fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1656    
1657            if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1658            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dx;
1659            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dy;
1660            if (fData->currentMV[1].y < bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1661    
1662          bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;          CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
         bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;  
         bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;  
         bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;  
         bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;  
         bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;  
         bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;  
         bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;  
   
         bData.bpredMV = fData.predMV = *f_predMV;  
         fData.bpredMV = bData.predMV = *b_predMV;  
   
   
         currentMV[0] = pMB->mvs[0];  
         currentMV[1] = pMB->b_mvs[0];  
         get_range(&fData.min_dx, &fData.max_dx, &fData.min_dy, &fData.max_dy, x, y, 16, pParam->width, pParam->height, fcode);  
         get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode);  
   
         CheckCandidateInt(currentMV[0].x, currentMV[0].y, 255, &iDirection, &fData);  
1663    
1664  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)
1665    
1666          do {          do {
1667                  iDirection = 255;                  iDirection = 255;
1668                  // forward MV moves                  // forward MV moves
1669                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
1670    
1671                  CheckCandidateInt(i + 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1672                  CheckCandidateInt(i, j + 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1673                  CheckCandidateInt(i - 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1674                  CheckCandidateInt(i, j - 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
1675    
1676                  // backward MV moves                  // backward MV moves
1677                  i = currentMV[1].x; j = currentMV[1].y;                  i = fData->currentMV[1].x; j = fData->currentMV[1].y;
1678                  currentMV[2] = currentMV[0];                  fData->currentMV[2] = fData->currentMV[0];
1679                    CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1680                  CheckCandidateInt(i + 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1681                  CheckCandidateInt(i, j + 2, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
1682                  CheckCandidateInt(i - 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, &bData);
                 CheckCandidateInt(i, j - 2, 0, &iDirection, &bData);  
1683    
1684          } while (!(iDirection));          } while (!(iDirection));
1685    
1686  /* halfpel refinement. luckly we can use normal halfpel function for it */          if (fData->qpel) {
   
         if (MotionFlags & PMV_HALFPELREFINE16) {  
1687                  CheckCandidate = CheckCandidateInt;                  CheckCandidate = CheckCandidateInt;
1688                  HalfpelRefine(&fData);                  fData->qpel_precision = bData.qpel_precision = 1;
1689                  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);
1690                  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);
1691          }                  fData->currentQMV[2].x = fData->currentQMV[0].x = 2 * fData->currentMV[0].x;
1692                    fData->currentQMV[2].y = fData->currentQMV[0].y = 2 * fData->currentMV[0].y;
1693  // 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;
1694          iMinSAD +=  2 * lambda_vec16[iQuant];                  fData->currentQMV[1].y = 2 * fData->currentMV[1].y;
1695          if (iMinSAD < *best_sad) {                  SubpelRefine(fData);
1696                  *best_sad = iMinSAD;                  fData->currentQMV[2] = fData->currentQMV[0];
1697                  pMB->mvs[0] = currentMV[0];                  SubpelRefine(&bData);
1698                  pMB->b_mvs[0] = currentMV[1];          }
1699    
1700            *fData->iMinSAD +=  (2+2) * fData->lambda16; // two bits are needed to code interpolate mode.
1701    
1702            if (*fData->iMinSAD < *best_sad) {
1703                    *best_sad = *fData->iMinSAD;
1704                    pMB->mvs[0] = fData->currentMV[0];
1705                    pMB->b_mvs[0] = fData->currentMV[1];
1706                  pMB->mode = MODE_INTERPOLATE;                  pMB->mode = MODE_INTERPOLATE;
1707                    if (fData->qpel) {
1708                            pMB->qmvs[0] = fData->currentQMV[0];
1709                            pMB->b_qmvs[0] = fData->currentQMV[1];
1710                            pMB->pmvs[1].x = pMB->qmvs[0].x - f_predMV->x;
1711                            pMB->pmvs[1].y = pMB->qmvs[0].y - f_predMV->y;
1712                            pMB->pmvs[0].x = pMB->b_qmvs[0].x - b_predMV->x;
1713                            pMB->pmvs[0].y = pMB->b_qmvs[0].y - b_predMV->y;
1714                    } else {
1715                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;
1716                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;
1717                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;
1718                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;
1719          }          }
1720  }  }
1721    }
1722    
1723  void  void
1724  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
# Line 1277  Line 1732 
1732                                           const IMAGE * const f_refV,                                           const IMAGE * const f_refV,
1733                                           const IMAGE * const f_refHV,                                           const IMAGE * const f_refHV,
1734                                           // backward (future) reference                                           // backward (future) reference
1735                                           const MACROBLOCK * const b_mbs,                                           const FRAMEINFO * const b_reference,
1736                                           const IMAGE * const b_ref,                                           const IMAGE * const b_ref,
1737                                           const IMAGE * const b_refH,                                           const IMAGE * const b_refH,
1738                                           const IMAGE * const b_refV,                                           const IMAGE * const b_refV,
1739                                           const IMAGE * const b_refHV)                                           const IMAGE * const b_refHV)
1740  {  {
1741          uint32_t i, j;          uint32_t i, j;
1742          int32_t best_sad, skip_sad;          int32_t best_sad;
1743            uint32_t skip_sad;
1744          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;
1745          static const VECTOR zeroMV={0,0};          static const VECTOR zeroMV={0,0};
1746            const MACROBLOCK * const b_mbs = b_reference->mbs;
1747    
1748          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
1749    
1750          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1751          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
1752            uint8_t * qimage;
1753    
1754          // note: i==horizontal, j==vertical  // some pre-inintialized data for the rest of the search
1755    
1756            SearchData Data;
1757            int32_t iMinSAD;
1758            VECTOR currentMV[3];
1759            VECTOR currentQMV[3];
1760            memset(&Data, 0, sizeof(SearchData));
1761            Data.iEdgedWidth = pParam->edged_width;
1762            Data.currentMV = currentMV; Data.currentQMV = currentQMV;
1763            Data.iMinSAD = &iMinSAD;
1764            Data.lambda16 = lambda_vec16[frame->quant];
1765            Data.chroma = frame->quant;
1766            Data.qpel = pParam->m_quarterpel;
1767            Data.rounding = 0;
1768    
1769            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
1770                    return; // allocate some mem for qpel interpolated blocks
1771                                      // somehow this is dirty since I think we shouldn't use malloc outside
1772                                      // encoder_create() - so please fix me!
1773            Data.RefQ = qimage;
1774    
1775            // note: i==horizontal, j==vertical
1776          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
1777    
1778                  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 1781 
1781                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;
1782                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;
1783    
1784  /* 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 */
1785                            if (b_reference->coding_type != S_VOP)
1786                          if (b_mb->mode == MODE_NOT_CODED) {                          if (b_mb->mode == MODE_NOT_CODED) {
1787                                  pMB->mode = MODE_NOT_CODED;                                  pMB->mode = MODE_NOT_CODED;
1788                                  continue;                                  continue;
1789                          }                          }
1790    
1791                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
1792                            pMB->quant = frame->quant;
1793    
1794  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
1795          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
1796                            skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
1797                          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,  
1798                                                                          &frame->image,                                                                          &frame->image,
1799                                                                          i, j,                                                                          i, j,
1800                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
1801                                                                          TRB, TRD,                                                                          TRB, TRD,
1802                                                                          pParam,                                                                          pParam,
1803                                                                          pMB, b_mb,                                                                          pMB, b_mb,
1804                                                                          &best_sad);                                                                          &best_sad,
1805                                                                            &Data);
1806    
                         if (!(frame->global_flags & XVID_HALFPEL)) best_sad = skip_sad = 256*4096;  
                         else  
1807                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1808    
 //                      best_sad = 256*4096; //uncomment to disable Directsearch.  
 //      To disable any other mode, just comment the function call  
   
1809                          // forward search                          // forward search
1810                          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,
1811                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1812                                                  frame->motion_flags,                                                  frame->motion_flags,
1813                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
1814                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
1815                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
1816    
1817                          // backward search                          // backward search
1818                          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,
1819                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1820                                                  frame->motion_flags,                                                  frame->motion_flags,
1821                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
1822                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
1823                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
1824    
1825                          // 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
1826    
# Line 1354  Line 1830 
1830                                                  i, j,                                                  i, j,
1831                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
1832                                                  frame->motion_flags,                                                  frame->motion_flags,
1833                                                  frame->quant, pParam,                                                  pParam,
1834                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
1835                                                  pMB, &best_sad);                                                  pMB, &best_sad,
1836                                                    &Data);
1837    
1838    // final skip decision
1839                            if ( (skip_sad < frame->quant * MAX_SAD00_FOR_SKIP*2)
1840                                            && ((100*best_sad)/(skip_sad+1) > FINAL_SKIP_THRESH) )
1841                                    SkipDecisionB(&frame->image, f_ref, b_ref, pMB,frame->quant, i, j, &Data);
1842    
1843                          switch (pMB->mode) {                          switch (pMB->mode) {
1844                                  case MODE_FORWARD:                                  case MODE_FORWARD:
1845                                          f_count++;                                          f_count++;
1846                                          f_predMV = pMB->mvs[0];                                          if (Data.qpel) f_predMV = pMB->qmvs[0];
1847                                            else f_predMV = pMB->mvs[0];
1848                                          break;                                          break;
1849                                  case MODE_BACKWARD:                                  case MODE_BACKWARD:
1850                                          b_count++;                                          b_count++;
1851                                          b_predMV = pMB->b_mvs[0];                                          if (Data.qpel) b_predMV = pMB->b_qmvs[0];
1852                                            else b_predMV = pMB->b_mvs[0];
1853                                          break;                                          break;
1854                                  case MODE_INTERPOLATE:                                  case MODE_INTERPOLATE:
1855                                          i_count++;                                          i_count++;
1856                                            if (Data.qpel) {
1857                                                    f_predMV = pMB->qmvs[0];
1858                                                    b_predMV = pMB->b_qmvs[0];
1859                                            } else {
1860                                          f_predMV = pMB->mvs[0];                                          f_predMV = pMB->mvs[0];
1861                                          b_predMV = pMB->b_mvs[0];                                          b_predMV = pMB->b_mvs[0];
1862                                            }
1863                                          break;                                          break;
1864                                  case MODE_DIRECT:                                  case MODE_DIRECT:
1865                                  case MODE_DIRECT_NO4V:                                  case MODE_DIRECT_NO4V:
1866                                          d_count++;                                          d_count++;
                                         break;  
1867                                  default:                                  default:
1868                                          break;                                          break;
1869                          }                          }
1870                  }                  }
1871          }          }
1872            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);  
   
1873  }  }
1874    
1875  /* Hinted ME starts here */  static __inline int
1876    MEanalyzeMB (   const uint8_t * const pRef,
1877  static __inline void                                  const uint8_t * const pCur,
 Search8hinted(  const SearchData * const OldData,  
                                 const int x, const int y,  
                                 const uint32_t MotionFlags,  
                                 const MBParam * const pParam,  
                                 MACROBLOCK * const pMB,  
                                 const MACROBLOCK * const pMBs,  
                                 const int block)  
 {  
         SearchData Data;  
         MainSearchFunc *MainSearchPtr;  
   
         Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);  
         Data.iMinSAD = OldData->iMinSAD + 1 + block;  
         Data.currentMV = OldData->currentMV+1+block;  
         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));  
   
         CheckCandidate = CheckCandidate8;  
   
         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);  
   
   
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,  
                                 pParam->width, pParam->height, OldData->iFcode);  
   
         if (pMB->mode == MODE_INTER4V) {  
                 int dummy;  
                 CheckCandidate8(pMB->mvs[block].x, pMB->mvs[block].y, 0, &dummy, &Data); }  
   
         if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;  
                 else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;  
                         else MainSearchPtr = DiamondSearch;  
   
         (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);  
   
         if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);  
   
         pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;  
         pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;  
         pMB->mvs[block] = *(Data.currentMV);  
         pMB->sad8[block] =  4 * (*(Data.iMinSAD));  
 }  
   
   
 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,  
1878                                  const int x,                                  const int x,
1879                                  const int y,                                  const int y,
                                 const uint32_t MotionFlags,  
                                 const uint32_t iQuant,  
                                 const uint32_t iFcode,  
1880                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1881                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1882                                  int inter4v,                                  MACROBLOCK * const pMB,
1883                                  MACROBLOCK * const pMB)                                  SearchData * const Data)
1884  {  {
1885    
1886          const int32_t iEdgedWidth = pParam->edged_width;          int i = 255, mask;
1887            VECTOR pmv[3];
1888            *(Data->iMinSAD) = MV_MAX_ERROR;
1889    
1890          int i;          //median is only used as prediction. it doesn't have to be real
1891          VECTOR currentMV[5];          if (x == 1 && y == 1) Data->predMV.x = Data->predMV.y = 0;
1892          int32_t iMinSAD[5];          else
1893          int32_t temp[5];                  if (x == 1) //left macroblock does not have any vector now
1894          MainSearchFunc * MainSearchPtr;                          Data->predMV = (pMB - pParam->mb_width)->mvs[0]; // top instead of median
1895          SearchData Data;                  else if (y == 1) // top macroblock don't have it's vector
1896                            Data->predMV = (pMB - 1)->mvs[0]; // left instead of median
1897                            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); //else median
1898    
1899            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1900                                    pParam->width, pParam->height, Data->iFcode - pParam->m_quarterpel, 0, 0);
1901    
1902            Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
1903            Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
1904    
1905            pmv[1].x = EVEN(pMB->mvs[0].x);
1906            pmv[1].y = EVEN(pMB->mvs[0].y);
1907            pmv[2].x = EVEN(Data->predMV.x);
1908            pmv[2].y = EVEN(Data->predMV.y);
1909            pmv[0].x = pmv[0].y = 0;
1910    
1911            CheckCandidate16no4vI(0, 0, 255, &i, Data);
1912    
1913    //early skip for 0,0
1914            if (*Data->iMinSAD < MAX_SAD00_FOR_SKIP * 4) {
1915                    pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1916                    pMB->mode = MODE_NOT_CODED;
1917                    return 0;
1918            }
1919    
1920          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          if (!(mask = make_mask(pmv, 1)))
1921          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,                  CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, Data);
1922                                  pParam->width, pParam->height, iFcode);          if (!(mask = make_mask(pmv, 2)))
1923                    CheckCandidate16no4vI(pmv[2].x, pmv[2].y, mask, &i, Data);
1924    
1925          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          if (*Data->iMinSAD > MAX_SAD00_FOR_SKIP * 6) // diamond only if needed
1926          Data.iEdgedWidth = iEdgedWidth;                  DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
         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;  
         Data.iQuant = iQuant;  
         Data.iFcode = iFcode;  
1927    
1928          if (!(MotionFlags & PMV_HALFPEL16)) {          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1929                  Data.min_dx = EVEN(Data.min_dx);          pMB->mode = MODE_INTER;
1930                  Data.max_dx = EVEN(Data.max_dx);          return *(Data->iMinSAD);
                 Data.min_dy = EVEN(Data.min_dy);  
                 Data.max_dy = EVEN(Data.max_dy);  
1931          }          }
1932    
1933          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;  #define INTRA_THRESH    1350
1934    #define INTER_THRESH    1200
1935    
         if (pMB->dquant != NO_CHANGE) inter4v = 0;  
1936    
1937          if (inter4v)  int
1938                  CheckCandidate = CheckCandidate16;  MEanalysis(     const IMAGE * const pRef,
1939          else CheckCandidate = CheckCandidate16no4v;                          FRAMEINFO * const Current,
1940                            MBParam * const pParam,
1941                            int maxIntra, //maximum number if non-I frames
1942          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);                          int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame
1943          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);                          int bCount) // number if B frames in a row
1944          if (pMB->mvs[0].x > Data.max_dx) pMB->mvs[0].x = Data.max_dx; // this is in case iFcode changed  {
1945          if (pMB->mvs[0].x < Data.min_dx) pMB->mvs[0].x = Data.min_dx;          uint32_t x, y, intra = 0;
1946          if (pMB->mvs[0].y > Data.max_dy) pMB->mvs[0].y = Data.max_dy;          int sSAD = 0;
1947          if (pMB->mvs[0].y < Data.min_dy) pMB->mvs[0].y = Data.min_dy;          MACROBLOCK * const pMBs = Current->mbs;
1948            const IMAGE * const pCurrent = &Current->image;
1949          CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);          int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH;
   
         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);  
                 }  
1950    
1951          if (MotionFlags & PMV_USESQUARES16)          VECTOR currentMV;
1952                  MainSearchPtr = SquareSearch;          int32_t iMinSAD;
1953          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)          SearchData Data;
1954                  MainSearchPtr = AdvDiamondSearch;          Data.iEdgedWidth = pParam->edged_width;
1955                  else MainSearchPtr = DiamondSearch;          Data.currentMV = &currentMV;
1956            Data.iMinSAD = &iMinSAD;
1957            Data.iFcode = Current->fcode;
1958            CheckCandidate = CheckCandidate16no4vI;
1959    
1960          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          if (intraCount < 10) // we're right after an I frame
1961                    IntraThresh += 4 * (intraCount - 10) * (intraCount - 10);
1962            else
1963                    if ( 5*(maxIntra - intraCount) < maxIntra) // we're close to maximum. 2 sec when max is 10 sec
1964                            IntraThresh -= (IntraThresh * (maxIntra - 5*(maxIntra - intraCount)))/maxIntra;
1965    
         if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);  
1966    
1967          if (inter4v)          InterThresh += 400 * (1 - bCount);
1968                  for(i = 0; i < 4; i++)          if (InterThresh < 200) InterThresh = 200;
                         Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);  
1969    
1970          if (!(inter4v) ||          if (sadInit) (*sadInit) ();
                 (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {  
 // INTER MODE  
1971    
1972                  pMB->mode = MODE_INTER;          for (y = 1; y < pParam->mb_height-1; y++) {
1973                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  for (x = 1; x < pParam->mb_width-1; x++) {
1974                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          int sad, dev;
1975                            MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
1976    
1977                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                          sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
1978                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                                                                  pParam, pMBs, pMB, &Data);
1979    
1980                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                          if (sad > IntraThresh) {
1981                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                                  dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
1982          } else {                                                            pParam->edged_width);
1983  // INTER4V MODE; all other things are already set in Search8hinted                                  if (dev + IntraThresh < sad) {
1984                  pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTRA;
1985                  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;
1986          }          }
1987                            }
1988                            sSAD += sad;
1989                    }
1990            }
1991            sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
1992            if (sSAD > InterThresh ) return P_VOP;
1993            emms();
1994            return B_VOP;
1995    
1996  }  }
1997    
1998  void  static void
1999  MotionEstimationHinted( MBParam * const pParam,  CheckGMC(int x, int y, const int dir, int * iDirection,
2000                                                  FRAMEINFO * const current,                  const MACROBLOCK * const pMBs, uint32_t * bestcount, VECTOR * GMC,
2001                                                  FRAMEINFO * const reference,                  const MBParam * const pParam)
                                                 const IMAGE * const pRefH,  
                                                 const IMAGE * const pRefV,  
                                                 const IMAGE * const pRefHV)  
2002  {  {
2003          MACROBLOCK *const pMBs = current->mbs;          uint32_t mx, my, a, count = 0;
         const IMAGE *const pCurrent = &current->image;  
         const IMAGE *const pRef = &reference->image;  
2004    
2005          uint32_t x, y;          for (my = 1; my < pParam->mb_height-1; my++)
2006                    for (mx = 1; mx < pParam->mb_width-1; mx++) {
2007                            VECTOR mv;
2008                            const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2009                            if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED) continue;
2010                            mv = pMB->mvs[0];
2011                            a = ABS(mv.x - x) + ABS(mv.y - y);
2012                            if (a < 6) count += 6 - a;
2013                    }
2014    
2015          if (sadInit) (*sadInit) ();          if (count > *bestcount) {
2016                    *bestcount = count;
2017                    *iDirection = dir;
2018                    GMC->x = x; GMC->y = y;
2019            }
2020    }
2021    
         for (y = 0; y < pParam->mb_height; y++) {  
                 for (x = 0; x < pParam->mb_width; x++)  {  
                         int32_t sad00;  
2022    
2023                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];  static VECTOR
2024    GlobalMotionEst(const MACROBLOCK * const pMBs, const MBParam * const pParam, const uint32_t iFcode)
2025    {
2026    
2027  //intra mode is copied from the first pass. At least for the time being          uint32_t count, bestcount = 0;
2028                          if  ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_NOT_CODED) ) continue;          int x, y;
2029            VECTOR gmc = {0,0};
2030            int step, min_x, max_x, min_y, max_y;
2031            uint32_t mx, my;
2032            int iDirection, bDirection;
2033    
2034                          if (!(current->global_flags & XVID_LUMIMASKING)) {          min_x = min_y = -32<<iFcode;
2035                                  pMB->dquant = NO_CHANGE;          max_x = max_y = 32<<iFcode;
                                 pMB->quant = current->quant; }  
2036    
2037                          if (pMB->dquant == NO_CHANGE) //no skip otherwise, anyway  //step1: let's find a rough camera panning
2038                                  sad00 = pMB->sad16          for (step = 32; step >= 2; step /= 2) {
2039                                          = sad16(pCurrent->y + (x + y * pParam->edged_width) * 16,                  bestcount = 0;
2040                                                                  pRef->y + (x + y * pParam->edged_width) * 16,                  for (y = min_y; y <= max_y; y += step)
2041                                                                  pParam->edged_width, 256*4096 );                          for (x = min_x ; x <= max_x; x += step) {
2042                          else sad00 = 256*4096;                                  count = 0;
2043                                    //for all macroblocks
2044                                    for (my = 1; my < pParam->mb_height-1; my++)
2045                                            for (mx = 1; mx < pParam->mb_width-1; mx++) {
2046                                                    const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2047                                                    VECTOR mv;
2048    
2049                                                    if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
2050                                                            continue;
2051    
2052  //initial skip decision                                                  mv = pMB->mvs[0];
2053                                                    if ( ABS(mv.x - x) <= step && ABS(mv.y - y) <= step )   /* GMC translation is always halfpel-res */
2054                                                            count++;
2055                                            }
2056                                    if (count >= bestcount) { bestcount = count; gmc.x = x; gmc.y = y; }
2057                            }
2058                    min_x = gmc.x - step;
2059                    max_x = gmc.x + step;
2060                    min_y = gmc.y - step;
2061                    max_y = gmc.y + step;
2062    
                         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  
2063                          }                          }
                         else sad00 = 256*4096;  
2064    
2065                          if (pMB->mode == MODE_NOT_CODED)          if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10)
2066                                  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);  
2067    
2068                          else  // step2: let's refine camera panning using gradiend-descent approach.
2069                                  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)
2070                                                          y, current->motion_flags, pMB->quant,          bestcount = 0;
2071                                                          current->fcode, pParam, pMBs,          CheckGMC(gmc.x, gmc.y, 255, &iDirection, pMBs, &bestcount, &gmc, pParam);
2072                                                          current->global_flags & XVID_INTER4V, pMB);          do {
2073                    x = gmc.x; y = gmc.y;
2074                    bDirection = iDirection; iDirection = 0;
2075                    if (bDirection & 1) CheckGMC(x - 1, y, 1+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2076                    if (bDirection & 2) CheckGMC(x + 1, y, 2+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2077                    if (bDirection & 4) CheckGMC(x, y - 1, 1+2+4, &iDirection, pMBs, &bestcount, &gmc, pParam);
2078                    if (bDirection & 8) CheckGMC(x, y + 1, 1+2+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2079    
2080  /* 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);  
2081    
2082                  }          if (pParam->m_quarterpel) {
2083          }                  gmc.x *= 2;
2084                    gmc.y *= 2;     /* we store the halfpel value as pseudo-qpel to make comparison easier */
2085  }  }
2086    
2087            return gmc;
2088    }

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

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