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

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

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