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

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

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