[svn] / branches / dev-api-3 / xvidcore / src / motion / motion_est.c Repository:
ViewVC logotype

Diff of /branches/dev-api-3/xvidcore/src/motion/motion_est.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 530, Mon Sep 23 20:36:02 2002 UTC revision 704, Wed Dec 11 10:32:29 2002 UTC
# Line 37  Line 37 
37  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
38  #include "../global.h"  #include "../global.h"
39  #include "../utils/timer.h"  #include "../utils/timer.h"
40    #include "../image/interpolate8x8.h"
41  #include "motion_est.h"  #include "motion_est.h"
42  #include "motion.h"  #include "motion.h"
43  #include "sad.h"  #include "sad.h"
44    #include "../utils/emms.h"
45    
46  #define INITIAL_SKIP_THRESH     (10)  #define INITIAL_SKIP_THRESH     (10)
47  #define FINAL_SKIP_THRESH       (50)  #define FINAL_SKIP_THRESH       (50)
48  #define MAX_SAD00_FOR_SKIP      (20)  #define MAX_SAD00_FOR_SKIP      (20)
49  #define MAX_CHROMA_SAD_FOR_SKIP (18)  #define MAX_CHROMA_SAD_FOR_SKIP (22)
50  #define SKIP_THRESH_B (10)  #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    
55  #define iDiamondSize 2  #define iDiamondSize 2
56    
57  //FILE * debug;  static VECTOR
58    GlobalMotionEst(const MACROBLOCK * const pMBs,
59                                    const MBParam * const pParam, const uint32_t iFcode);
60    
61    
62  static __inline int  static __inline int
63  d_mv_bits(int x, int y, const uint32_t iFcode)  d_mv_bits(int x, int y, const uint32_t iFcode)
# Line 79  Line 84 
84          return xb + yb;          return xb + yb;
85  }  }
86    
87  /* CHACK_CANDIATE FUNCTIONS START */  static int32_t
88    ChromaSAD(int dx, int dy, const SearchData * const data)
89    {
90            int sad;
91            dx = (dx >> 1) + roundtab_79[dx & 0x3];
92            dy = (dy >> 1) + roundtab_79[dy & 0x3];
93    
94            switch (((dx & 1) << 1) + (dy & 1))     { // ((dx%2)?2:0)+((dy%2)?1:0)
95                    case 0:
96                            sad = sad8(data->CurU, data->RefCU + (dy/2) * (data->iEdgedWidth/2) + dx/2, data->iEdgedWidth/2);
97                            sad += sad8(data->CurV, data->RefCV + (dy/2) * (data->iEdgedWidth/2) + dx/2, data->iEdgedWidth/2);
98                            break;
99                    case 1:
100                            dx = dx / 2; dy = (dy - 1) / 2;
101                            sad = sad8bi(data->CurU, data->RefCU + dy * (data->iEdgedWidth/2) + dx, data->RefCU + (dy+1) * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2);
102                            sad += sad8bi(data->CurV, data->RefCV + dy * (data->iEdgedWidth/2) + dx, data->RefCV + (dy+1) * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2);
103                            break;
104                    case 2:
105                            dx = (dx - 1) / 2; dy = dy / 2;
106                            sad = sad8bi(data->CurU, data->RefCU + dy * (data->iEdgedWidth/2) + dx, data->RefCU + dy * (data->iEdgedWidth/2) + dx+1, data->iEdgedWidth/2);
107                            sad += sad8bi(data->CurV, data->RefCV + dy * (data->iEdgedWidth/2) + dx, data->RefCV + dy * (data->iEdgedWidth/2) + dx+1, data->iEdgedWidth/2);
108                            break;
109                    default:
110                            dx = (dx - 1) / 2; dy = (dy - 1) / 2;
111                            interpolate8x8_halfpel_hv(data->RefQ,
112                                                                             data->RefCU + dy * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2,
113                                                                             data->rounding);
114                            sad = sad8(data->CurU, data->RefQ, data->iEdgedWidth/2);
115                            interpolate8x8_halfpel_hv(data->RefQ,
116                                                                             data->RefCV + dy * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2,
117                                                                             data->rounding);
118                            sad += sad8(data->CurV, data->RefQ, data->iEdgedWidth/2);
119                            break;
120            }
121            return sad;
122    }
123    
124    static __inline const uint8_t *
125    GetReference(const int x, const int y, const int dir, const SearchData * const data)
126    {
127    //      dir : 0 = forward, 1 = backward
128            switch ( (dir << 2) | ((x&1)<<1) | (y&1) ) {
129                    case 0 : return data->Ref + x/2 + (y/2)*(data->iEdgedWidth);
130                    case 1 : return data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth);
131                    case 2 : return data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth);
132                    case 3 : return data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth);
133                    case 4 : return data->bRef + x/2 + (y/2)*(data->iEdgedWidth);
134                    case 5 : return data->bRefV + x/2 + ((y-1)/2)*(data->iEdgedWidth);
135                    case 6 : return data->bRefH + (x-1)/2 + (y/2)*(data->iEdgedWidth);
136                    default : return data->bRefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth);
137    
138            }
139    }
140    
141    static uint8_t *
142    Interpolate8x8qpel(const int x, const int y, const int block, const int dir, const SearchData * const data)
143    {
144    // create or find a qpel-precision reference picture; return pointer to it
145            uint8_t * Reference = (uint8_t *)data->RefQ + 16*dir;
146            const int32_t iEdgedWidth = data->iEdgedWidth;
147            const uint32_t rounding = data->rounding;
148            const int halfpel_x = x/2;
149            const int halfpel_y = y/2;
150            const uint8_t *ref1, *ref2, *ref3, *ref4;
151    
152            ref1 = GetReference(halfpel_x, halfpel_y, dir, data); // this reference is used in all cases
153            ref1 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
154            switch( ((x&1)<<1) + (y&1) ) {
155            case 0: // pure halfpel position
156                    Reference = (uint8_t *) GetReference(halfpel_x, halfpel_y, dir, data);
157                    Reference += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
158                    break;
159    
160            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
161                    ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);
162                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
163                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
164                    break;
165    
166            case 2: // x qpel, y halfpel - left or right during qpel refinement
167                    ref2 = GetReference(x - halfpel_x, halfpel_y, dir, data);
168                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
169                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
170                    break;
171    
172            default: // x and y in qpel resolution - the "corners" (top left/right and
173                             // bottom left/right) during qpel refinement
174                    ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);
175                    ref3 = GetReference(x - halfpel_x, halfpel_y, dir, data);
176                    ref4 = GetReference(x - halfpel_x, y - halfpel_y, dir, data);
177                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
178                    ref3 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
179                    ref4 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
180                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
181                    break;
182            }
183            return Reference;
184    }
185    
186    static uint8_t *
187    Interpolate16x16qpel(const int x, const int y, const int dir, const SearchData * const data)
188    {
189    // create or find a qpel-precision reference picture; return pointer to it
190            uint8_t * Reference = (uint8_t *)data->RefQ + 16*dir;
191            const int32_t iEdgedWidth = data->iEdgedWidth;
192            const uint32_t rounding = data->rounding;
193            const int halfpel_x = x/2;
194            const int halfpel_y = y/2;
195            const uint8_t *ref1, *ref2, *ref3, *ref4;
196    
197            ref1 = GetReference(halfpel_x, halfpel_y, dir, data); // this reference is used in all cases
198            switch( ((x&1)<<1) + (y&1) ) {
199            case 0: // pure halfpel position
200                    return (uint8_t *) GetReference(halfpel_x, halfpel_y, dir, data);
201            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
202                    ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);
203                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
204                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
205                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
206                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
207                    break;
208    
209            case 2: // x qpel, y halfpel - left or right during qpel refinement
210                    ref2 = GetReference(x - halfpel_x, 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            default: // x and y in qpel resolution - the "corners" (top left/right and
218                             // bottom left/right) during qpel refinement
219                    ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);
220                    ref3 = GetReference(x - halfpel_x, halfpel_y, dir, data);
221                    ref4 = GetReference(x - halfpel_x, y - halfpel_y, dir, data);
222                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
223                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
224                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
225                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
226                    break;
227            }
228            return Reference;
229    }
230    
231    /* CHECK_CANDIATE FUNCTIONS START */
232    
233  static void  static void
234  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)
235  {  {
236          int32_t * const sad = data->temp;          int t, xc, yc;
 //      static int32_t sad[5];  
         int t;  
237          const uint8_t * Reference;          const uint8_t * Reference;
238            VECTOR * current;
239    
240          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
241                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
242    
243            if (data->qpel_precision) { // x and y are in 1/4 precision
244                    Reference = Interpolate16x16qpel(x, y, 0, data);
245                    t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
246                    xc = x/2; yc = y/2; //for chroma sad
247                    current = data->currentQMV;
248            } else {
249          switch ( ((x&1)<<1) + (y&1) ) {          switch ( ((x&1)<<1) + (y&1) ) {
250                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;
251                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;
252                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;
253                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;
254          }          }
255                    if (data->qpel) t = d_mv_bits(2*x - data->predMV.x, 2*y - data->predMV.y, data->iFcode);
256                    else t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
257                    current = data->currentMV;
258                    xc = x; yc = y;
259            }
260    
261          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, sad+1);          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
262    
263          t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          data->temp[0] += (data->lambda16 * t * data->temp[0])/1000;
264          data->temp[0] += lambda_vec16[data->iQuant] * t;          data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))/100;
265          data->temp[1] += lambda_vec8[data->iQuant] * t;  
266            if (data->chroma) data->temp[0] += ChromaSAD(xc, yc, data);
267    
268            if (data->temp[0] < data->iMinSAD[0]) {
269                    data->iMinSAD[0] = data->temp[0];
270                    current[0].x = x; current[0].y = y;
271                    *dir = Direction; }
272    
273            if (data->temp[1] < data->iMinSAD[1]) {
274                    data->iMinSAD[1] = data->temp[1]; current[1].x = x; current[1].y= y; }
275            if (data->temp[2] < data->iMinSAD[2]) {
276                    data->iMinSAD[2] = data->temp[2]; current[2].x = x; current[2].y = y; }
277            if (data->temp[3] < data->iMinSAD[3]) {
278                    data->iMinSAD[3] = data->temp[3]; current[3].x = x; current[3].y = y; }
279            if (data->temp[4] < data->iMinSAD[4]) {
280                    data->iMinSAD[4] = data->temp[4]; current[4].x = x; current[4].y = y; }
281    
282    }
283    
284    static void
285    CheckCandidate32(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
286    {
287            int t;
288            const uint8_t * Reference;
289    
290            if ( (!(x&1) && x !=0) || (!(y&1) && y !=0) || //non-zero integer value
291                    ( x > data->max_dx) || ( x < data->min_dx)
292                    || ( y > data->max_dy) || (y < data->min_dy)) return;
293    
294            switch ( ((x&1)<<1) + (y&1) ) {
295                    case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;
296                    case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;
297                    case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;
298                    default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;
299            }
300    
301            t = d_mv_bits(RRV_MV_SCALEDOWN(x) - data->predMV.x,
302                                            RRV_MV_SCALEDOWN(y) - data->predMV.y, data->iFcode);
303    
304            data->temp[0] = sad32v_c(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
305    
306            data->temp[0] += (data->lambda16 * t * data->temp[0])/1000;
307            data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))/100;
308    
309          if (data->temp[0] < data->iMinSAD[0]) {          if (data->temp[0] < data->iMinSAD[0]) {
310                  data->iMinSAD[0] = data->temp[0];                  data->iMinSAD[0] = data->temp[0];
# Line 118  Line 319 
319                  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; }
320          if (data->temp[4] < data->iMinSAD[4]) {          if (data->temp[4] < data->iMinSAD[4]) {
321                  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; }
   
322  }  }
323    
324  static void  static void
# Line 126  Line 326 
326  {  {
327          int32_t sad;          int32_t sad;
328          const uint8_t * Reference;          const uint8_t * Reference;
329            int t;
330            VECTOR * current;
331    
332          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
333                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
334    
335          switch ( ((x&1)<<1) + (y&1) )          if (data->rrv) {
336          {                  if ( (!(x&1) && x !=0) || (!(y&1) && y !=0) ) return; //non-zero integer value
337                    t = d_mv_bits(RRV_MV_SCALEDOWN(x) - data->predMV.x,
338                                            RRV_MV_SCALEDOWN(y) - data->predMV.y, data->iFcode);
339            }
340    
341            if (data->qpel_precision) { // x and y are in 1/4 precision
342                    Reference = Interpolate16x16qpel(x, y, 0, data);
343                    t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
344                    current = data->currentQMV;
345            } else {
346                    switch ( ((x&1)<<1) + (y&1) ) {
347                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;
348                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;
349                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;
350                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;
351          }          }
352                    if (data->qpel) t = d_mv_bits(2*x - data->predMV.x, 2*y - data->predMV.y, data->iFcode);
353                    else if (!data->rrv) t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
354                    current = data->currentMV;
355            }
356    
357            sad = sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);
358            sad += (data->lambda16 * t * sad)/1000;
359    
360            if (sad < *(data->iMinSAD)) {
361                    *(data->iMinSAD) = sad;
362                    current->x = x; current->y = y;
363                    *dir = Direction; }
364    }
365    
366          sad = lambda_vec16[data->iQuant] *  static void
367                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);  CheckCandidate16no4vI(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
368          sad += sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);  {
369    // maximum speed - for P/B/I decision
370            int32_t sad;
371    
372            if (( x > data->max_dx) || ( x < data->min_dx)
373                    || ( y > data->max_dy) || (y < data->min_dy)) return;
374    
375            sad = sad16(data->Cur, data->Ref + x/2 + (y/2)*(data->iEdgedWidth),
376                                            data->iEdgedWidth, 256*4096);
377    
378          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
379                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 148  Line 381 
381                  *dir = Direction; }                  *dir = Direction; }
382  }  }
383    
384    
385  static void  static void
386  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)
387  {  {
388          int32_t sad;          int32_t sad;
389          const int xb = data->currentMV[1].x;          int xb, yb, t;
         const int yb = data->currentMV[1].y;  
390          const uint8_t *ReferenceF, *ReferenceB;          const uint8_t *ReferenceF, *ReferenceB;
391            VECTOR *current;
392    
393          if (( xf > data->max_dx) || ( xf < data->min_dx)          if (( xf > data->max_dx) || ( xf < data->min_dx)
394                  || ( yf > data->max_dy) || (yf < data->min_dy)) return;                  || ( yf > data->max_dy) || (yf < data->min_dy)) return;
395    
396          switch ( ((xf&1)<<1) + (yf&1) ) {          if (data->qpel_precision) {
397                  case 0 : ReferenceF = data->Ref + xf/2 + (yf/2)*(data->iEdgedWidth); break;                  ReferenceF = Interpolate16x16qpel(xf, yf, 0, data);
398                  case 1 : ReferenceF = data->RefV + xf/2 + ((yf-1)/2)*(data->iEdgedWidth); break;                  xb = data->currentQMV[1].x; yb = data->currentQMV[1].y;
399                  case 2 : ReferenceF = data->RefH + (xf-1)/2 + (yf/2)*(data->iEdgedWidth); break;                  current = data->currentQMV;
400                  default : ReferenceF = data->RefHV + (xf-1)/2 + ((yf-1)/2)*(data->iEdgedWidth); break;                  ReferenceB = Interpolate16x16qpel(xb, yb, 1, data);
401          }                  t = d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode)
402                                     + d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode);
403          switch ( ((xb&1)<<1) + (yb&1) ) {          } else {
404                  case 0 : ReferenceB = data->bRef + xb/2 + (yb/2)*(data->iEdgedWidth); break;                  ReferenceF = Interpolate16x16qpel(2*xf, 2*yf, 0, data);
405                  case 1 : ReferenceB = data->bRefV + xb/2 + ((yb-1)/2)*(data->iEdgedWidth); break;                  xb = data->currentMV[1].x; yb = data->currentMV[1].y;
406                  case 2 : ReferenceB = data->bRefH + (xb-1)/2 + (yb/2)*(data->iEdgedWidth); break;                  ReferenceB = Interpolate16x16qpel(2*xb, 2*yb, 1, data);
407                  default : ReferenceB = data->bRefHV + (xb-1)/2 + ((yb-1)/2)*(data->iEdgedWidth); break;                  current = data->currentMV;
408                    if (data->qpel)
409                            t = d_mv_bits(2*xf - data->predMV.x, 2*yf - data->predMV.y, data->iFcode)
410                                             + d_mv_bits(2*xb - data->bpredMV.x, 2*yb - data->bpredMV.y, data->iFcode);
411                    else
412                            t = d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode)
413                                             + d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode);
414          }          }
415    
416          sad = lambda_vec16[data->iQuant] *          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
417                          ( d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode) +          sad += (data->lambda16 * t * sad)/1000;
                           d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode) );  
   
         sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);  
418    
419          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
420                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
421                  data->currentMV->x = xf; data->currentMV->y = yf;                  current->x = xf; current->y = yf;
422                  *dir = Direction; }                  *dir = Direction; }
423  }  }
424    
425  static void  static void
426  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)
427  {  {
428          int32_t sad;          int32_t sad = 0;
429          int k;          int k;
430          const uint8_t *ReferenceF;          const uint8_t *ReferenceF;
431          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
# Line 196  Line 433 
433    
434          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
435    
         sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);  
   
436          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
437                  mvs.x = data->directmvF[k].x + x;                  mvs.x = data->directmvF[k].x + x;
438                  b_mvs.x = ((x == 0) ?                  b_mvs.x = ((x == 0) ?
# Line 214  Line 449 
449                          || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )                          || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )
450                          || ( 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;
451    
452                  switch ( ((mvs.x&1)<<1) + (mvs.y&1) ) {                  if (!data->qpel) {
453                          case 0 : ReferenceF = data->Ref + mvs.x/2 + (mvs.y/2)*(data->iEdgedWidth); break;                          mvs.x *= 2; mvs.y *= 2;
454                          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;  
455                  }                  }
456                    ReferenceF = Interpolate8x8qpel(mvs.x, mvs.y, k, 0, data);
457                    ReferenceB = Interpolate8x8qpel(b_mvs.x, b_mvs.y, k, 1, data);
458    
459                  sad += sad8bi(data->Cur + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),                  sad += sad8bi(data->Cur + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
460                                                  ReferenceF + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),                                                  ReferenceF, ReferenceB,
                                                 ReferenceB + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),  
461                                                  data->iEdgedWidth);                                                  data->iEdgedWidth);
462                  if (sad > *(data->iMinSAD)) return;                  if (sad > *(data->iMinSAD)) return;
463          }          }
464    
465            sad += (data->lambda16 * d_mv_bits(x, y, 1) * sad)/1000;
466    
467          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
468                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
469                  data->currentMV->x = x; data->currentMV->y = y;                  data->currentMV->x = x; data->currentMV->y = y;
# Line 249  Line 478 
478          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
479          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
480    
481          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);  
482    
483          mvs.x = data->directmvF[0].x + x;          mvs.x = data->directmvF[0].x + x;
484          b_mvs.x = ((x == 0) ?          b_mvs.x = ((x == 0) ?
# Line 268  Line 495 
495                  || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )                  || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )
496                  || ( 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;
497    
498          switch ( ((mvs.x&1)<<1) + (mvs.y&1) ) {          if (!data->qpel) {
499                  case 0 : ReferenceF = data->Ref + mvs.x/2 + (mvs.y/2)*(data->iEdgedWidth); break;                          mvs.x *= 2; mvs.y *= 2;
500                  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;  
501          }          }
502            ReferenceF = Interpolate16x16qpel(mvs.x, mvs.y, 0, data);
503            ReferenceB = Interpolate16x16qpel(b_mvs.x, b_mvs.y, 1, data);
504    
505          sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
506            sad += (data->lambda16 * d_mv_bits(x, y, 1) * sad)/1000;
507    
508          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
509                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 293  Line 514 
514  static void  static void
515  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)
516  {  {
517          int32_t sad;          int32_t sad; int t;
518          const uint8_t * Reference;          const uint8_t * Reference;
519    
520          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
521                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
522    
523          switch ( ((x&1)<<1) + (y&1) )          if (data->qpel) Reference = Interpolate16x16qpel(x, y, 0, data);
524          {          else Reference = Interpolate16x16qpel(2*x, 2*y, 0, data);
                 case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;  
                 case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;  
                 case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;  
                 default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;  
         }  
525    
526          sad = sad8(data->Cur, Reference, data->iEdgedWidth);          sad = sad8(data->Cur, Reference, data->iEdgedWidth);
527          sad += lambda_vec8[data->iQuant] * d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          if (data->qpel) t = d_mv_bits(2 * x - data->predMV.x, 2 * y - data->predMV.y, data->iFcode);
528            else t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
529    
530            sad += (data->lambda8 * t * (sad+NEIGH_8X8_BIAS))/100;
531    
532          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
533                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 316  Line 535 
535                  *dir = Direction; }                  *dir = Direction; }
536  }  }
537    
538  /* CHACK_CANDIATE FUNCTIONS END */  /* CHECK_CANDIATE FUNCTIONS END */
539    
540  /* MAINSEARCH FUNCTIONS START */  /* MAINSEARCH FUNCTIONS START */
541    
# Line 465  Line 684 
684  /* 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 */
685    
686  static void  static void
687  HalfpelRefine(const SearchData * const data)  SubpelRefine(const SearchData * const data)
688  {  {
689  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a half-pel or q-pel refinement */
690            VECTOR backupMV;
         VECTOR backupMV = *(data->currentMV);  
691          int iDirection; //not needed          int iDirection; //not needed
692    
693            if (data->qpel_precision)
694                    backupMV = *(data->currentQMV);
695            else backupMV = *(data->currentMV);
696    
697          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);
698          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);
699          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);
# Line 487  Line 709 
709  static __inline int  static __inline int
710  SkipDecisionP(const IMAGE * current, const IMAGE * reference,  SkipDecisionP(const IMAGE * current, const IMAGE * reference,
711                                                          const int x, const int y,                                                          const int x, const int y,
712                                                          const uint32_t iEdgedWidth, const uint32_t iQuant)                                                          const uint32_t iEdgedWidth, const uint32_t iQuant, int rrv)
713    
714  {  {
715  /*      keep repeating checks for all b-frames before this P frame,  /*      keep repeating checks for all b-frames before this P frame,
716          to make sure that SKIP is possible (todo)          to make sure that SKIP is possible (todo)
717          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 */
718            if(rrv) {
719                    uint32_t sadC = sad16(current->u + x*16 + y*(iEdgedWidth/2)*16,
720                                                    reference->u + x*16 + y*(iEdgedWidth/2)*16, iEdgedWidth/2, 256*4096);
721                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP*4) return 0;
722                    sadC += sad16(current->v + (x + y*(iEdgedWidth/2))*16,
723                                                    reference->v + (x + y*(iEdgedWidth/2))*16, iEdgedWidth/2, 256*4096);
724                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP*4) return 0;
725                    return 1;
726            } else {
727          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,
728                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);
729          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
730          sadC += sad8(current->v + x*8 + y*(iEdgedWidth/2)*8,                  sadC += sad8(current->v + (x + y*(iEdgedWidth/2))*8,
731                                          reference->v + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                                  reference->v + (x + y*(iEdgedWidth/2))*8, iEdgedWidth/2);
732          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
   
733          return 1;          return 1;
734  }  }
735    }
736    
737  static __inline void  static __inline void
738  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)  SkipMacroblockP(MACROBLOCK *pMB, const int32_t sad)
739  {  {
740          pMB->mode = MODE_NOT_CODED;          pMB->mode = MODE_NOT_CODED;
741          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = pMB->mv16.x = 0;          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;
742          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = pMB->mv16.y = 0;          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;
743    
744            pMB->qmvs[0].x = pMB->qmvs[1].x = pMB->qmvs[2].x = pMB->qmvs[3].x = 0;
745            pMB->qmvs[0].y = pMB->qmvs[1].y = pMB->qmvs[2].y = pMB->qmvs[3].y = 0;
746    
747          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;
748  }  }
749    
# Line 528  Line 762 
762    
763          const VECTOR zeroMV = { 0, 0 };          const VECTOR zeroMV = { 0, 0 };
764    
765            uint32_t mb_width = pParam->mb_width;
766            uint32_t mb_height = pParam->mb_height;
767    
768          uint32_t x, y;          uint32_t x, y;
769          uint32_t iIntra = 0;          uint32_t iIntra = 0;
770          int32_t InterBias;          int32_t InterBias, quant = current->quant, sad00;
771            uint8_t *qimage;
772    
773            // some pre-initialized thingies for SearchP
774            int32_t temp[5];
775            VECTOR currentMV[5];
776            VECTOR currentQMV[5];
777            int32_t iMinSAD[5];
778            SearchData Data;
779            memset(&Data, 0, sizeof(SearchData));
780            Data.iEdgedWidth = pParam->edged_width;
781            Data.currentMV = currentMV;
782            Data.currentQMV = currentQMV;
783            Data.iMinSAD = iMinSAD;
784            Data.temp = temp;
785            Data.iFcode = current->fcode;
786            Data.rounding = pParam->m_rounding_type;
787            Data.qpel = pParam->m_quarterpel;
788            Data.chroma = current->global_flags & XVID_ME_COLOUR;
789            Data.rrv = current->global_flags & XVID_REDUCED;
790    
791            if ((current->global_flags & XVID_REDUCED)) {
792                    mb_width = (pParam->width + 31) / 32;
793                    mb_height = (pParam->height + 31) / 32;
794                    Data.qpel = Data.chroma = 0;
795            }
796    
797            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
798                    return 1; // allocate some mem for qpel interpolated blocks
799                                      // somehow this is dirty since I think we shouldn't use malloc outside
800                                      // encoder_create() - so please fix me!
801            Data.RefQ = qimage;
802          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
803    
804          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < mb_height; y++) {
805                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < mb_width; x++)  {
   
806                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
807                          int32_t sad00 =  pMB->sad16  
808                                  = sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,                          if (Data.rrv) pMB->sad16 =
809                                    sad32v_c(pCurrent->y + (x + y * pParam->edged_width) * 32,
810                                                            pRef->y + (x + y * pParam->edged_width) * 32,
811                                                            pParam->edged_width, pMB->sad8 );
812    
813                            else pMB->sad16 =
814                                    sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,
815                                                          pRef->y + (x + y * pParam->edged_width) * 16,                                                          pRef->y + (x + y * pParam->edged_width) * 16,
816                                                          pParam->edged_width, pMB->sad8 );                                                          pParam->edged_width, pMB->sad8 );
817    
818                            if (Data.chroma) {
819                                    pMB->sad16 += sad8(pCurrent->u + x*8 + y*(pParam->edged_width/2)*8,
820                                                                    pRef->u + x*8 + y*(pParam->edged_width/2)*8, pParam->edged_width/2);
821    
822                                    pMB->sad16 += sad8(pCurrent->v + (x + y*(pParam->edged_width/2))*8,
823                                                                    pRef->v + (x + y*(pParam->edged_width/2))*8, pParam->edged_width/2);
824                            }
825    
826                            sad00 = pMB->sad16; //if no gmc; else sad00 = (..)
827    
828                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
829                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
830                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant;
831                            } else {
832                                    if (pMB->dquant != NO_CHANGE) {
833                                            quant += DQtab[pMB->dquant];
834                                            if (quant > 31) quant = 31;
835                                            else if (quant < 1) quant = 1;
836                                    }
837                                    pMB->quant = quant;
838                            }
839    
840  //initial skip decision  //initial skip decision
841    /* no early skip for GMC (global vector = skip vector is unknown!)  */
842                          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 */
843                                  && (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) )
844                                  if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {                                          if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant, Data.rrv)) {
845                                                  SkipMacroblockP(pMB, sad00);                                                  SkipMacroblockP(pMB, sad00);
846                                                  continue;                                                  continue;
847                                  }                                  }
848                          } else sad00 = 256*4096; // skip not allowed - for final skip decision                          }
849    
850                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchP(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
851                                                  y, current->motion_flags, pMB->quant,                                                  y, current->motion_flags, pMB->quant,
852                                                  current->fcode, pParam, pMBs, reference->mbs,                                                  &Data, pParam, pMBs, reference->mbs,
853                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
854    
855  /* 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?" */
856                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)                          if (current->coding_type == P_VOP)      {
857                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)                                  if ( (pMB->dquant == NO_CHANGE) && (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)
858                                  { SkipMacroblockP(pMB, sad00); continue; }                                          && ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH * (Data.rrv ? 4:1)) )
859                                            if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant, Data.rrv)) {
860                                                    SkipMacroblockP(pMB, sad00);
861                                                    continue;
862                                            }
863                            }
864    
865  /* finally, intra decision */  /* finally, intra decision */
866    
867                          InterBias = MV16_INTER_BIAS;                          InterBias = MV16_INTER_BIAS;
868                          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
869                          if (y != 0)                          if (y != 0)
870                                  if ((pMB - pParam->mb_width)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - pParam->mb_width)->mode == MODE_INTRA ) InterBias -= 80;
871                          if (x != 0)                          if (x != 0)
872                                  if ((pMB - 1)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - 1)->mode == MODE_INTRA ) InterBias -= 80;
873    
874                            if (Data.chroma) InterBias += 50; // to compensate bigger SAD
875                            if (Data.rrv) InterBias *= 4; //??
876    
877                          if (InterBias < pMB->sad16)  {                          if (InterBias < pMB->sad16)  {
878                                  const int32_t deviation =                                  int32_t deviation;
879                                          dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                  if (Data.rrv) {
880                                            deviation = dev16(pCurrent->y + (x + y * pParam->edged_width) * 32,
881                                                                                    pParam->edged_width)
882                                                    + dev16(pCurrent->y + (x + y * pParam->edged_width) * 32 + 16,
883                                                                                    pParam->edged_width)
884                                                    + dev16(pCurrent->y + (x + y * pParam->edged_width) * 32 + 16 * pParam->edged_width,
885                                                                                    pParam->edged_width)
886                                                    + dev16(pCurrent->y + (x + y * pParam->edged_width) * 32 + 16 * (pParam->edged_width+1),
887                                                                                    pParam->edged_width);
888                                    } else
889                                            deviation = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
890                                                    pParam->edged_width);                                                    pParam->edged_width);
891    
892                                  if (deviation < (pMB->sad16 - InterBias)) {                                  if (deviation < (pMB->sad16 - InterBias)) {
893                                          if (++iIntra >= iLimit) return 1;                                          if (++iIntra >= iLimit) { free(qimage); return 1; }
894                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
895                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
896                                                  pMB->mvs[3] = zeroMV;                                                  pMB->mvs[3] = zeroMV;
897                                            pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] =
898                                                            pMB->qmvs[3] = zeroMV;
899                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
900                                                  pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
901                                  }                                  }
902                          }                          }
903                  }                  }
904          }          }
905            free(qimage);
906    
907            if (current->coding_type == S_VOP)      /* first GMC step only for S(GMC)-VOPs */
908                    current->GMC_MV = GlobalMotionEst( pMBs, pParam, current->fcode );
909            else
910                    current->GMC_MV = zeroMV;
911    
912          return 0;          return 0;
913  }  }
914    
# Line 601  Line 918 
918  static __inline int  static __inline int
919  make_mask(const VECTOR * const pmv, const int i)  make_mask(const VECTOR * const pmv, const int i)
920  {  {
921          int mask = 0xFF, j;          int mask = 255, j;
922          for (j = 0; j < i; j++) {          for (j = 0; j < i; j++) {
923                  if (MVequal(pmv[i], pmv[j])) return 0; // same vector has been checked already                  if (MVequal(pmv[i], pmv[j])) return 0; // same vector has been checked already
924                  if (pmv[i].x == pmv[j].x) {                  if (pmv[i].x == pmv[j].x) {
# Line 617  Line 934 
934  }  }
935    
936  static __inline void  static __inline void
937  PreparePredictionsP(VECTOR * const pmv, int x, int y, const int iWcount,  PreparePredictionsP(VECTOR * const pmv, int x, int y, int iWcount,
938                          const int iHcount, const MACROBLOCK * const prevMB)                          int iHcount, const MACROBLOCK * const prevMB, int rrv)
939  {  {
940    
941  //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
942            if (rrv) { iWcount /= 2; iHcount /= 2; }
943    
944          if ( (y != 0) && (x != (iWcount-1)) ) {         // [5] top-right neighbour          if ( (y != 0) && (x < (iWcount-1)) ) {          // [5] top-right neighbour
945                  pmv[5].x = EVEN(pmv[3].x);                  pmv[5].x = EVEN(pmv[3].x);
946                  pmv[5].y = EVEN(pmv[3].y); }                  pmv[5].y = EVEN(pmv[3].y);
947          else pmv[5].x = pmv[5].y = 0;          } else pmv[5].x = pmv[5].y = 0;
948    
949          if (x != 0) { pmv[3].x = EVEN(pmv[1].x); pmv[3].y = EVEN(pmv[1].y); }// pmv[3] is left neighbour          if (x != 0) { pmv[3].x = EVEN(pmv[1].x); pmv[3].y = EVEN(pmv[1].y); }// pmv[3] is left neighbour
950          else pmv[3].x = pmv[3].y = 0;          else pmv[3].x = pmv[3].y = 0;
# Line 635  Line 953 
953      else pmv[4].x = pmv[4].y = 0;      else pmv[4].x = pmv[4].y = 0;
954    
955          // [1] median prediction          // [1] median prediction
956          pmv[1].x = EVEN(pmv[0].x); pmv[1].y = EVEN(pmv[0].y);          if (rrv) { //median is in halfzero-precision
957                    pmv[1].x = RRV_MV_SCALEUP(pmv[0].x);
958                    pmv[1].y = RRV_MV_SCALEUP(pmv[0].y);
959            } else { pmv[1].x = EVEN(pmv[0].x); pmv[1].y = EVEN(pmv[0].y); }
960    
961          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
962    
963          pmv[2].x = EVEN(prevMB->mvs[0].x); // [2] is last frame          pmv[2].x = EVEN(prevMB->mvs[0].x); // [2] is last frame
964          pmv[2].y = EVEN(prevMB->mvs[0].y);          pmv[2].y = EVEN(prevMB->mvs[0].y);
965    
966          if ((x != iWcount-1) && (y != iHcount-1)) {          if ((x < iWcount-1) && (y < iHcount-1)) {
967                  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
968                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y); }                  pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
969          else pmv[6].x = pmv[6].y = 0;          } else pmv[6].x = pmv[6].y = 0;
970    
971            if (rrv) {
972                    int i;
973                    for (i = 0; i < 7; i++) {
974                            pmv[i].x = RRV_MV_SCALEDOWN(pmv[i].x);
975                            pmv[i].x = RRV_MV_SCALEUP(pmv[i].x); // a trick
976                    }
977            }
978  }  }
979    
980  static void  static void
981  SearchP(const uint8_t * const pRef,  SearchP(const IMAGE * const pRef,
982                  const uint8_t * const pRefH,                  const uint8_t * const pRefH,
983                  const uint8_t * const pRefV,                  const uint8_t * const pRefV,
984                  const uint8_t * const pRefHV,                  const uint8_t * const pRefHV,
# Line 658  Line 987 
987                  const int y,                  const int y,
988                  const uint32_t MotionFlags,                  const uint32_t MotionFlags,
989                  const uint32_t iQuant,                  const uint32_t iQuant,
990                  const uint32_t iFcode,                  SearchData * const Data,
991                  const MBParam * const pParam,                  const MBParam * const pParam,
992                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
993                  const MACROBLOCK * const prevMBs,                  const MACROBLOCK * const prevMBs,
# Line 666  Line 995 
995                  MACROBLOCK * const pMB)                  MACROBLOCK * const pMB)
996  {  {
997    
         const int32_t iEdgedWidth = pParam->edged_width;  
   
998          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
999          int32_t temp[5];          VECTOR pmv[7];
         VECTOR currentMV[5], pmv[7];  
         int32_t psad[4], iMinSAD[5];  
         MainSearchFunc * MainSearchPtr;  
         SearchData Data;  
1000    
1001          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, psad);  //has to be changed to get_pmv(2)()          if (Data->rrv) {
1002          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,                  i = (pParam->width + 31) / 32;
1003                                  pParam->width, pParam->height, iFcode);                  get_range_rrv(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 32,
1004                                                    pParam->width, pParam->height, Data->iFcode);
1005            } else {
1006                    i = pParam->mb_width;
1007                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1008                            pParam->width, pParam->height, Data->iFcode - pParam->m_quarterpel);
1009            }
1010    
1011            i = pParam->mb_width; // XXXX
1012            get_pmvdata2(pMBs, i, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()
1013    
1014            if (Data->rrv) i = 2; else i = 1;
1015            Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16*i;
1016            Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
1017            Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
1018    
1019            Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16*i;
1020            Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16*i;
1021            Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16*i;
1022            Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16*i;
1023            Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
1024            Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
1025    
1026            Data->lambda16 = lambda_vec16[iQuant];
1027            Data->lambda8 = lambda_vec8[iQuant];
1028            Data->qpel_precision = 0;
1029    
1030          Data.predMV = pmv[0];          if (pMB->dquant != NO_CHANGE) inter4v = 0;
         Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
         Data.iEdgedWidth = iEdgedWidth;  
         Data.currentMV = currentMV;  
         Data.iMinSAD = iMinSAD;  
         Data.Ref = pRef + (x + iEdgedWidth*y)*16;  
         Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;  
         Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;  
         Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;  
         Data.temp = temp;  
1031    
1032          Data.iQuant = iQuant;          for(i = 0;  i < 5; i++)
1033          Data.iFcode = iFcode;                  Data->currentMV[i].x = Data->currentMV[i].y = 0;
1034    
1035          if (!(MotionFlags & PMV_HALFPEL16)) {          if (pParam->m_quarterpel) Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1036                  Data.min_dx = EVEN(Data.min_dx);          else Data->predMV = pmv[0];
                 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++) currentMV[i].x = currentMV[i].y = 0;  
   
         i = d_mv_bits(pmv[0].x, pmv[0].y, iFcode);  
   
         iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;  
         iMinSAD[1] = pMB->sad8[0] + lambda_vec8[iQuant] * i;  
         iMinSAD[2] = pMB->sad8[1];  
         iMinSAD[3] = pMB->sad8[2];  
         iMinSAD[4] = pMB->sad8[3];  
1037    
1038          if (pMB->dquant != NO_CHANGE) inter4v = 0;          i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);
1039            Data->iMinSAD[0] = pMB->sad16 + (Data->lambda16 * i * pMB->sad16)/1000;
1040            Data->iMinSAD[1] = pMB->sad8[0] + (Data->lambda8 * i * (pMB->sad8[0]+NEIGH_8X8_BIAS))/100;
1041            Data->iMinSAD[2] = pMB->sad8[1];
1042            Data->iMinSAD[3] = pMB->sad8[2];
1043            Data->iMinSAD[4] = pMB->sad8[3];
1044    
1045          if ((x == 0) && (y == 0)) threshA = 512;          if ((x == 0) && (y == 0)) threshA = 512;
1046          else {          else {
1047                  threshA = psad[0] + 20;                  threshA = Data->temp[0]; // that's when we keep this SAD atm
1048                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
1049                  if (threshA > 1024) threshA = 1024; }                  if (threshA > 1024) threshA = 1024; }
1050    
1051          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,
1052                                          prevMBs + x + y * pParam->mb_width);                                          prevMBs + x + y * pParam->mb_width, Data->rrv);
1053    
1054          if (inter4v) CheckCandidate = CheckCandidate16;          if (Data->rrv) CheckCandidate = CheckCandidate32;
1055          else CheckCandidate = CheckCandidate16no4v;          else if (inter4v || Data->chroma) CheckCandidate = CheckCandidate16;
1056                    else CheckCandidate = CheckCandidate16no4v; //for extra speed
1057    
1058  /* main loop. checking all predictions */  /* main loop. checking all predictions */
1059    
1060          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
1061                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1062                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  (*CheckCandidate)(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1063                  if (iMinSAD[0] < threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
1064          }          }
1065    
1066          if ((iMinSAD[0] <= threshA) ||          if ((Data->iMinSAD[0] <= threshA) ||
1067                          (MVequal(currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&                          (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
1068                          (iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {                          (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16))) {
1069                  inter4v = 0;                  inter4v = 0;
1070                  if (MotionFlags & PMV_QUICKSTOP16) goto PMVfast16_Terminate_without_Refine;          } else {
                 if (MotionFlags & PMV_EARLYSTOP16) {  
                         CheckCandidate = CheckCandidate16no4v; // I sure hope it's faster  
                         goto PMVfast16_Terminate_with_Refine;  
                 }  
         }  
1071    
1072          if (MotionFlags & PMV_USESQUARES16)                  MainSearchFunc * MainSearchPtr;
1073                  MainSearchPtr = SquareSearch;                  if (MotionFlags & PMV_USESQUARES16) MainSearchPtr = SquareSearch;
1074          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
                 MainSearchPtr = AdvDiamondSearch;  
1075                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1076    
1077          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, iDirection);                  (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, iDirection);
1078    
1079  /* extended search, diamond starting in 0,0 and in prediction.  /* extended search, diamond starting in 0,0 and in prediction.
1080          note that this search is/might be done in halfpel positions,          note that this search is/might be done in halfpel positions,
# Line 756  Line 1082 
1082    
1083          if (MotionFlags & PMV_EXTSEARCH16) {          if (MotionFlags & PMV_EXTSEARCH16) {
1084                  int32_t bSAD;                  int32_t bSAD;
1085                  VECTOR startMV = Data.predMV, backupMV = currentMV[0];                          VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
1086                            if (Data->rrv) {
1087                                    startMV.x = RRV_MV_SCALEUP(startMV.x);
1088                                    startMV.y = RRV_MV_SCALEUP(startMV.y);
1089                            } else
1090                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?                  if (!(MotionFlags & PMV_HALFPELREFINE16)) // who's gonna use extsearch and no halfpel?
1091                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);                          startMV.x = EVEN(startMV.x); startMV.y = EVEN(startMV.y);
1092                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1093                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1094    
1095                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1096                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1097                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1098                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1099                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1100                  }                  }
1101    
1102                  backupMV = currentMV[0];                          backupMV = Data->currentMV[0];
1103                  if (MotionFlags & PMV_HALFPELREFINE16) startMV.x = startMV.y = 1;                          if (!MotionFlags & PMV_HALFPELREFINE16 || Data->rrv) startMV.x = startMV.y = 0;
1104                  else startMV.x = startMV.y = 0;                          else startMV.x = startMV.y = 1;
1105                  if (!(MVequal(startMV, backupMV))) {                  if (!(MVequal(startMV, backupMV))) {
1106                          bSAD = iMinSAD[0]; iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1107    
1108                          CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, &Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1109                          (*MainSearchPtr)(startMV.x, startMV.y, &Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1110                          if (bSAD < iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1111                                  currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
1112                                  iMinSAD[0] = bSAD; }                                          Data->iMinSAD[0] = bSAD; }
1113                  }                  }
1114          }          }
1115            }
1116    
1117            if (MotionFlags & PMV_HALFPELREFINE16) SubpelRefine(Data);
1118    
1119            for(i = 0; i < 5; i++) {
1120                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1121                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1122            }
1123    
1124            if((!Data->rrv) && (pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1125    
1126                    Data->qpel_precision = 1;
1127                    get_range_qpel(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1128                                    pParam->width, pParam->height, Data->iFcode);
1129    
1130                    SubpelRefine(Data);
1131            }
1132    
1133  PMVfast16_Terminate_with_Refine:          if (Data->iMinSAD[0] < (int32_t)iQuant * 30 ) inter4v = 0;
1134            if (inter4v) {
1135                    SearchData Data8;
1136                    Data8.iFcode = Data->iFcode;
1137                    Data8.lambda8 = Data->lambda8;
1138                    Data8.iEdgedWidth = Data->iEdgedWidth;
1139                    Data8.RefQ = Data->RefQ;
1140                    Data8.qpel = Data->qpel;
1141                    Data8.rrv = Data->rrv;
1142                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1143                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1144                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1145                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1146    
1147          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);                  if (Data->chroma) {
1148                            int sumx, sumy, dx, dy;
1149    
1150  PMVfast16_Terminate_without_Refine:                          if(pParam->m_quarterpel) {
1151                                    sumx= pMB->qmvs[0].x/2 + pMB->qmvs[1].x/2 + pMB->qmvs[2].x/2 + pMB->qmvs[3].x/2;
1152                                    sumy = pMB->qmvs[0].y/2 + pMB->qmvs[1].y/2 + pMB->qmvs[2].y/2 + pMB->qmvs[3].y/2;
1153                            } else {
1154                                    sumx = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1155                                    sumy = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1156                            }
1157                            dx = (sumx >> 3) + roundtab_76[sumx & 0xf];
1158                            dy = (sumy >> 3) + roundtab_76[sumy & 0xf];
1159    
1160          if (inter4v)                          Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);
1161                  for(i = 0; i < 4; i++)                  }
1162                          Search8(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);          }
1163    
1164            if (Data->rrv) {
1165                            Data->currentMV[0].x = RRV_MV_SCALEDOWN(Data->currentMV[0].x);
1166                            Data->currentMV[0].y = RRV_MV_SCALEDOWN(Data->currentMV[0].y);
1167            }
1168          if (!(inter4v) ||          if (!(inter4v) ||
1169                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
1170                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1171  // INTER MODE  // INTER MODE
1172                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1173                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1174                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1175    
1176                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1177                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1178    
1179                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1180                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->qmvs[0] = pMB->qmvs[1]
1181                                    = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1182                            pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predMV.x;
1183                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predMV.y;
1184                    } else {
1185                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1186                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1187                    }
1188          } else {          } else {
1189  // INTER4V MODE; all other things are already set in Search8  // INTER4V MODE; all other things are already set in Search8
1190                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1191                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1192                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1193          }          }
   
1194  }  }
1195    
1196  static void  static void
# Line 820  Line 1200 
1200                  const MBParam * const pParam,                  const MBParam * const pParam,
1201                  MACROBLOCK * const pMB,                  MACROBLOCK * const pMB,
1202                  const MACROBLOCK * const pMBs,                  const MACROBLOCK * const pMBs,
1203                  const int block)                  const int block,
1204                    SearchData * const Data)
1205  {  {
1206          SearchData Data;          int i = 0;
1207            Data->iMinSAD = OldData->iMinSAD + 1 + block;
1208          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          Data->currentMV = OldData->currentMV + 1 + block;
1209          Data.iMinSAD = OldData->iMinSAD + 1 + block;          Data->currentQMV = OldData->currentQMV + 1 + block;
1210          Data.currentMV = OldData->currentMV+1+block;  
1211          Data.iFcode = OldData->iFcode;          if(pParam->m_quarterpel) {
1212          Data.iQuant = OldData->iQuant;                  Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2, y/2, block);
1213                    if (block != 0) i = d_mv_bits(  Data->currentQMV->x - Data->predMV.x,
1214          if (block != 0)                                                                                  Data->currentQMV->y - Data->predMV.y, Data->iFcode);
1215                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *          } else {
1216                                                                  d_mv_bits(      Data.currentMV->x - Data.predMV.x,                  Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2, y/2, block);
1217                                                                                          Data.currentMV->y - Data.predMV.y,                  if (block != 0) {
1218                                                                                          Data.iFcode);                          if (Data->rrv) i = d_mv_bits(   RRV_MV_SCALEDOWN(Data->currentMV->x) - Data->predMV.x,
1219                                                                                            RRV_MV_SCALEDOWN(Data->currentMV->y) - Data->predMV.y,
1220                                                                                            Data->iFcode);
1221                            else i = d_mv_bits(     Data->currentMV->x - Data->predMV.x,
1222                                                                    Data->currentMV->y - Data->predMV.y, Data->iFcode);
1223                    }
1224            }
1225    
1226            *(Data->iMinSAD) += (Data->lambda8 * i * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
1227    
1228          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
1229                    if (Data->rrv) i = 2; else i = 1;
1230    
1231                  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));
1232                  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));
1233                  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));
1234                  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));
1235    
1236                  Data.iEdgedWidth = pParam->edged_width;                  Data->Cur = OldData->Cur + i*8 * ((block&1) + pParam->edged_width*(block>>1));
1237                    Data->qpel_precision = 0;
1238    
1239                  Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                  if (Data->rrv) {
1240                            get_range_rrv(&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, 8,  
1241                                  pParam->width, pParam->height, OldData->iFcode);                                  pParam->width, pParam->height, OldData->iFcode);
1242                            CheckCandidate = CheckCandidate16no4v;
1243                    } else {
1244                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1245                                            pParam->width, pParam->height, OldData->iFcode - pParam->m_quarterpel);
1246                  CheckCandidate = CheckCandidate8;                  CheckCandidate = CheckCandidate8;
1247                    }
1248    
1249                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & PMV_EXTSEARCH8) {
1250                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1251    
1252                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1253                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1254                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1255                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1256    
1257                          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);     }                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1258    
1259                            if(*(Data->iMinSAD) < temp_sad) {
1260                                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1261                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1262                            }
1263                    }
1264    
1265                    if (MotionFlags & PMV_HALFPELREFINE8) {
1266                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1267    
1268                            SubpelRefine(Data); // perform halfpel refine of current best vector
1269    
1270                            if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1271                                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1272                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1273                            }
1274                    }
1275    
1276                    if(!Data->rrv && pParam->m_quarterpel) {
1277                            if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1278                                    (MotionFlags & PMV_QUARTERPELREFINE8)) {
1279                            Data->qpel_precision = 1;
1280                            get_range_qpel(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1281                                    pParam->width, pParam->height, OldData->iFcode);
1282                            SubpelRefine(Data);
1283                            }
1284                    }
1285            }
1286    
1287                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);          if (Data->rrv) {
1288                            Data->currentMV->x = RRV_MV_SCALEDOWN(Data->currentMV->x);
1289                            Data->currentMV->y = RRV_MV_SCALEDOWN(Data->currentMV->y);
1290          }          }
1291    
1292          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;          if(pParam->m_quarterpel) {
1293          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;                  pMB->pmvs[block].x = Data->currentQMV->x - Data->predMV.x;
1294          pMB->mvs[block] = *(Data.currentMV);                  pMB->pmvs[block].y = Data->currentQMV->y - Data->predMV.y;
1295          pMB->sad8[block] =  4 * (*(Data.iMinSAD));                  pMB->qmvs[block] = *(Data->currentQMV);
1296            } else {
1297                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1298                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1299            }
1300    
1301            pMB->mvs[block] = *(Data->currentMV);
1302            pMB->sad8[block] =  4 * (*Data->iMinSAD);
1303  }  }
1304    
1305  /* B-frames code starts here */  /* B-frames code starts here */
# Line 896  Line 1327 
1327          pmv[2] = ChoosePred(pMB, mode_curr);          pmv[2] = ChoosePred(pMB, mode_curr);
1328          pmv[2].x = EVEN(pmv[2].x); pmv[2].y = EVEN(pmv[2].y);          pmv[2].x = EVEN(pmv[2].x); pmv[2].y = EVEN(pmv[2].y);
1329    
         pmv[3].x = pmv[3].y = 0;  
1330          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour          if ((y != 0)&&(x != (int)(iWcount+1))) {                        // [3] top-right neighbour
1331                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);                  pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr);
1332                  pmv[3].x = EVEN(pmv[3].x); pmv[3].y = EVEN(pmv[3].y); }                  pmv[3].x = EVEN(pmv[3].x); pmv[3].y = EVEN(pmv[3].y);
1333            } else pmv[3].x = pmv[3].y = 0;
1334    
1335          if (y != 0) {          if (y != 0) {
1336                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);                  pmv[4] = ChoosePred(pMB-iWcount, mode_curr);
# Line 929  Line 1360 
1360                          const IMAGE * const pCur,                          const IMAGE * const pCur,
1361                          const int x, const int y,                          const int x, const int y,
1362                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
1363                          const uint32_t iFcode,                          const uint32_t iFcode,
1364                          const MBParam * const pParam,                          const MBParam * const pParam,
1365                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
1366                          const VECTOR * const predMV,                          const VECTOR * const predMV,
1367                          int32_t * const best_sad,                          int32_t * const best_sad,
1368                          const int32_t mode_current)                          const int32_t mode_current,
1369                            SearchData * const Data)
1370  {  {
1371    
1372          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1373    
1374          int i, iDirection, mask;          int i, iDirection, mask;
1375          VECTOR currentMV, pmv[7];          VECTOR pmv[7];
1376          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1377          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
1378          SearchData Data;          Data->iFcode = iFcode;
1379            Data->qpel_precision = 0;
         Data.iMinSAD = &iMinSAD;  
         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);  
1380    
1381          if (!(MotionFlags & PMV_HALFPEL16)) {          Data->Ref = pRef + (x + y * iEdgedWidth) * 16;
1382                  Data.min_dx = EVEN(Data.min_dx);          Data->RefH = pRefH + (x + y * iEdgedWidth) * 16;
1383                  Data.max_dx = EVEN(Data.max_dx);          Data->RefV = pRefV + (x + y * iEdgedWidth) * 16;
1384                  Data.min_dy = EVEN(Data.min_dy);          Data->RefHV = pRefHV + (x + y * iEdgedWidth) * 16;
                 Data.max_dy = EVEN(Data.max_dy); } // no-halpel and b-frames. do we need it?  
1385    
1386            Data->predMV = *predMV;
1387    
1388          pmv[0] = Data.predMV;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1389          PreparePredictionsBF(pmv, x, y, pParam->mb_width,                                  pParam->width, pParam->height, iFcode - pParam->m_quarterpel);
                                         pMB, mode_current);  
1390    
1391          currentMV.x = currentMV.y = 0;          pmv[0] = Data->predMV;
1392            if (Data->qpel) { pmv[0].x /= 2; pmv[0].y /= 2; }
1393            PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
1394    
1395            Data->currentMV->x = Data->currentMV->y = 0;
1396          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1397    
1398  // main loop. checking all predictions  // main loop. checking all predictions
1399          for (i = 0; i < 8; i++) {          for (i = 0; i < 8; i++) {
1400                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1401                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1402          }          }
1403    
1404          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 990  Line 1407 
1407                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1408                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1409    
1410          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1411    
1412            SubpelRefine(Data);
1413    
1414          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (Data->qpel) {
1415                    Data->currentQMV->x = 2*Data->currentMV->x;
1416                    Data->currentQMV->y = 2*Data->currentMV->y;
1417                    Data->qpel_precision = 1;
1418                    get_range_qpel(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1419                                            pParam->width, pParam->height, iFcode);
1420                    SubpelRefine(Data);
1421            }
1422    
1423  // three bits are needed to code backward mode. four for forward  // three bits are needed to code backward mode. four for forward
1424  // we treat the bits just like they were vector's  // we treat the bits just like they were vector's
1425          if (mode_current == MODE_FORWARD) iMinSAD +=  4 * lambda_vec16[iQuant];          if (mode_current == MODE_FORWARD) *Data->iMinSAD +=  4 * Data->lambda16;
1426          else iMinSAD +=  3 * lambda_vec16[iQuant];          else *Data->iMinSAD +=  3 * Data->lambda16;
1427    
1428            if (*Data->iMinSAD < *best_sad) {
1429          if (iMinSAD < *best_sad) {                  *best_sad = *Data->iMinSAD;
                 *best_sad = iMinSAD;  
1430                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1431                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  if (Data->qpel) {
1432                  pMB->pmvs[0].y = currentMV.y - predMV->y;                          pMB->pmvs[0].x = Data->currentQMV->x - predMV->x;
1433                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                          pMB->pmvs[0].y = Data->currentQMV->y - predMV->y;
1434                  else pMB->b_mvs[0] = currentMV;                          if (mode_current == MODE_FORWARD)
1435                                    pMB->qmvs[0] = *Data->currentQMV;
1436                            else
1437                                    pMB->b_qmvs[0] = *Data->currentQMV;
1438                    } else {
1439                            pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1440                            pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1441                    }
1442                    if (mode_current == MODE_FORWARD)
1443                            pMB->mvs[0] = *(Data->currentMV+2) = *Data->currentMV;
1444                    else
1445                            pMB->b_mvs[0] = *(Data->currentMV+1) = *Data->currentMV; //we store currmv for interpolate search
1446    
1447          }          }
1448    
1449  }  }
1450    
1451  static int32_t  static int32_t
1452  SearchDirect(const uint8_t * const f_Ref,  SearchDirect(const IMAGE * const f_Ref,
1453                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
1454                                  const uint8_t * const f_RefV,                                  const uint8_t * const f_RefV,
1455                                  const uint8_t * const f_RefHV,                                  const uint8_t * const f_RefHV,
1456                                  const uint8_t * const b_Ref,                                  const IMAGE * const b_Ref,
1457                                  const uint8_t * const b_RefH,                                  const uint8_t * const b_RefH,
1458                                  const uint8_t * const b_RefV,                                  const uint8_t * const b_RefV,
1459                                  const uint8_t * const b_RefHV,                                  const uint8_t * const b_RefHV,
1460                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1461                                  const int x, const int y,                                  const int x, const int y,
1462                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1463                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1464                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1465                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1466                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1467                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1468                                    SearchData * const Data)
1469    
1470  {  {
1471          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
         int32_t iMinSAD = 0, skip_sad;  
1472          int k;          int k;
1473          VECTOR currentMV;  
1474          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
         SearchData Data;  
1475    
1476          Data.iMinSAD = &iMinSAD;          *Data->iMinSAD = 256*4096;
         Data.Cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;  
         Data.iEdgedWidth = iEdgedWidth;  
         Data.currentMV = &currentMV;  
         Data.iQuant = iQuant;  
         Data.referencemv = b_mb->mvs;  
1477    
1478          Data.Ref= f_Ref + (x + iEdgedWidth*y) * 16;          Data->Ref = f_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1479          Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;          Data->RefH = f_RefH + (x + Data->iEdgedWidth*y) * 16;
1480          Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;          Data->RefV = f_RefV + (x + Data->iEdgedWidth*y) * 16;
1481          Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = f_RefHV + (x + Data->iEdgedWidth*y) * 16;
1482          Data.bRef = b_Ref + (x + iEdgedWidth*y) * 16;          Data->bRef = b_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1483          Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;          Data->bRefH = b_RefH + (x + Data->iEdgedWidth*y) * 16;
1484          Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;          Data->bRefV = b_RefV + (x + Data->iEdgedWidth*y) * 16;
1485          Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;          Data->bRefHV = b_RefHV + (x + Data->iEdgedWidth*y) * 16;
1486  /*  
1487  //What we do here is a complicated version of CheckCandidateDirect(0,0);          Data->max_dx = 2 * pParam->width - 2 * (x) * 16;
1488  get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16, pParam->width, pParam->height, 19);          Data->max_dy = 2 * pParam->height - 2 * (y) * 16;
1489            Data->min_dx = -(2 * 16 + 2 * (x) * 16);
1490  */          Data->min_dy = -(2 * 16 + 2 * (y) * 16);
1491          Data.max_dx = 2 * pParam->width - 2 * (x) * 16;          if (Data->qpel) { //we measure in qpixels
1492          Data.max_dy = 2 * pParam->height - 2 * (y) * 16;                  Data->max_dx *= 2;
1493          Data.min_dx = -(2 * 16 + 2 * (x) * 16);                  Data->max_dy *= 2;
1494          Data.min_dy = -(2 * 16 + 2 * (y) * 16);                  Data->min_dx *= 2;
1495                    Data->min_dy *= 2;
1496                    Data->referencemv = b_mb->qmvs;
1497            } else Data->referencemv = b_mb->mvs;
1498            Data->qpel_precision = 0; // it's a trick. it's 1 not 0, but we need 0 here
1499    
1500          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1501                  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);
1502                  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;
1503                  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);
1504                  pMB->b_mvs[k].y = Data.directmvB[k].y = ((TRB - TRD) * Data.referencemv[k].y) / TRD;                  pMB->b_mvs[k].y = Data->directmvB[k].y = ((TRB - TRD) * Data->referencemv[k].y) / TRD;
   
         if (( pMB->mvs[k].x > Data.max_dx ) || ( pMB->mvs[k].x < Data.min_dx )  
                         || ( pMB->mvs[k].y > Data.max_dy ) || ( pMB->mvs[k].y < Data.min_dy )  
                         || ( pMB->b_mvs[k].x > Data.max_dx ) || ( pMB->b_mvs[k].x < Data.min_dx )  
                         || ( pMB->b_mvs[k].y > Data.max_dy ) || ( pMB->b_mvs[k].y < Data.min_dy )) {  
 /*  
                 fprintf(debug, "\nERROR - out of range : vector %d,%d and %d,%d\n", pMB->mvs[k].x, pMB->mvs[k].y,pMB->b_mvs[k].x,pMB->b_mvs[k].y );  
                 fprintf(debug, " range is x: %d..%d y: %d..%d \n", Data.min_dx,Data.max_dx,Data.min_dy,Data.max_dy);  
                 fprintf(debug,"macroblock %d, %d \n", x, y);  
                 fprintf(debug, "direct MV is %d,%d \n", directmv[k].x, directmv[k].y);  
 */  
                 *best_sad = 256*4096; // in that case, we won't use direct mode  
                 pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"  
                 pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;  /* because backwards and interpol might rely on this */  
                 return 0; }  
1505    
1506                    if ( ( pMB->b_mvs[k].x > Data->max_dx ) || ( pMB->b_mvs[k].x < Data->min_dx )
1507                            || ( pMB->b_mvs[k].y > Data->max_dy ) || ( pMB->b_mvs[k].y < Data->min_dy )) {
1508    
1509                            *best_sad = 256*4096; // in that case, we won't use direct mode
1510                            pMB->mode = MODE_DIRECT; // just to make sure it doesn't say "MODE_DIRECT_NONE_MV"
1511                            pMB->b_mvs[0].x = pMB->b_mvs[0].y = 0;
1512                            return 0;
1513                    }
1514          if (b_mb->mode != MODE_INTER4V) {          if (b_mb->mode != MODE_INTER4V) {
1515                  iMinSAD = sad16bi(Data.Cur,                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1516                                                  get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,                          pMB->b_mvs[1] = pMB->b_mvs[2] = pMB->b_mvs[3] = pMB->b_mvs[0];
1517                                                                  x, y, 16, &pMB->mvs[0], iEdgedWidth),                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1518                                                  get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1519                                                                  x, y, 16, &pMB->b_mvs[0], iEdgedWidth), iEdgedWidth);                          break;
   
                 Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];  
                 Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];  
                 break;  
         }  
         iMinSAD += sad8bi(Data.Cur + (k&1)*8 + (k>>1)* 8 * iEdgedWidth,  
                                                 get_ref_mv(f_Ref, f_RefH, f_RefV, f_RefHV,  
                                                                 (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->mvs[k], iEdgedWidth),  
                                                 get_ref_mv(b_Ref, b_RefH, b_RefV, b_RefHV,  
                                                                 (2*x+(k&1)), (2*y+(k>>1)), 8, &pMB->b_mvs[k], iEdgedWidth),  
                                                 iEdgedWidth);  
1520          }          }
1521            }
1522    
1523    
1524            if (b_mb->mode == MODE_INTER4V) CheckCandidate = CheckCandidateDirect;
1525            else CheckCandidate = CheckCandidateDirectno4v;
1526    
1527            (*CheckCandidate)(0, 0, 255, &k, Data);
1528    
1529  // skip decision  // skip decision
1530          if (iMinSAD < (int32_t)iQuant * SKIP_THRESH_B) {          if (*Data->iMinSAD < pMB->quant * SKIP_THRESH_B) {
1531                    //possible skip - checking chroma. everything copied from MC
1532                    //this is not full chroma compensation, only it's fullpel approximation. should work though
1533                    int sum, dx, dy, b_dx, b_dy;
1534    
1535                    if (Data->qpel) {
1536                            sum = pMB->mvs[0].y/2 + pMB->mvs[1].y/2 + pMB->mvs[2].y/2 + pMB->mvs[3].y/2;
1537                            dy = (sum >> 3) + roundtab_76[sum & 0xf];
1538                            sum = pMB->mvs[0].x/2 + pMB->mvs[1].x/2 + pMB->mvs[2].x/2 + pMB->mvs[3].x/2;
1539                            dx = (sum >> 3) + roundtab_76[sum & 0xf];
1540    
1541                            sum = pMB->b_mvs[0].y/2 + pMB->b_mvs[1].y/2 + pMB->b_mvs[2].y/2 + pMB->b_mvs[3].y/2;
1542                            b_dy = (sum >> 3) + roundtab_76[sum & 0xf];
1543                            sum = pMB->b_mvs[0].x/2 + pMB->b_mvs[1].x/2 + pMB->b_mvs[2].x/2 + pMB->b_mvs[3].x/2;
1544                            b_dx = (sum >> 3) + roundtab_76[sum & 0xf];
1545    
1546                    } else {
1547                            sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1548                            dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1549                            sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1550                            dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1551    
1552                            sum = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;
1553                            b_dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1554                            sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;
1555                            b_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1556                    }
1557                    sum = sad8bi(pCur->u + 8*x + 8*y*(Data->iEdgedWidth/2),
1558                                            f_Ref->u + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1559                                            b_Ref->u + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1560                                            Data->iEdgedWidth/2);
1561                    sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1562                                            f_Ref->v + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1563                                            b_Ref->v + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1564                                            Data->iEdgedWidth/2);
1565    
1566                    if (sum < MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) {
1567                  pMB->mode = MODE_DIRECT_NONE_MV;                  pMB->mode = MODE_DIRECT_NONE_MV;
1568                  return iMinSAD; }                          return *Data->iMinSAD;
1569                    }
1570            }
1571    
1572          skip_sad = iMinSAD;          skip_sad = *Data->iMinSAD;
         iMinSAD += 2 * lambda_vec16[iQuant]; // 2 bits needed to code vector 0,0  
         currentMV.x = currentMV.y = 0;  
         if (b_mb->mode == MODE_INTER4V)  
                 CheckCandidate = CheckCandidateDirect;  
         else CheckCandidate = CheckCandidateDirectno4v;  
1573    
1574  //  DIRECT MODE DELTA VECTOR SEARCH.  //  DIRECT MODE DELTA VECTOR SEARCH.
1575  //      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 1123  Line 1578 
1578                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1579                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1580    
1581          (*MainSearchPtr)(0, 0, &Data, 255);          (*MainSearchPtr)(0, 0, Data, 255);
1582    
1583          HalfpelRefine(&Data);          SubpelRefine(Data);
1584    
1585          iMinSAD +=  1 * lambda_vec16[iQuant]; // one bit is needed to code direct mode. we treat this bit just like it was vector's  //      *Data->iMinSAD +=  1 * Data->lambda16; // one bit is needed to code direct mode
1586          *best_sad = iMinSAD;          *best_sad = *Data->iMinSAD;
1587    
1588          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1589                  pMB->mode = MODE_DIRECT;                  pMB->mode = MODE_DIRECT;
1590          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1591    
1592          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1593    
1594          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1595                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1596                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = (     (Data->currentMV->x == 0)
1597                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1598                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          :pMB->mvs[k].x - Data->referencemv[k].x);
1599                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1600                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1601                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1602                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1603                    if (Data->qpel) {
1604                            pMB->qmvs[k].x = pMB->mvs[k].x; pMB->mvs[k].x /= 2;
1605                            pMB->b_qmvs[k].x = pMB->b_mvs[k].x; pMB->b_mvs[k].x /= 2;
1606                            pMB->qmvs[k].y = pMB->mvs[k].y; pMB->mvs[k].y /= 2;
1607                            pMB->b_qmvs[k].y = pMB->b_mvs[k].y; pMB->b_mvs[k].y /= 2;
1608                    }
1609    
1610                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1611                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1612                          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];
1613                            pMB->qmvs[3] = pMB->qmvs[2] = pMB->qmvs[1] = pMB->qmvs[0];
1614                            pMB->b_qmvs[3] = pMB->b_qmvs[2] = pMB->b_qmvs[1] = pMB->b_qmvs[0];
1615                          break;                          break;
1616                  }                  }
1617          }          }
1618          return 0;//skip_sad;          return skip_sad;
1619  }  }
1620    
1621    
1622  static __inline void  static __inline void
1623  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const uint8_t * const f_Ref,
1624                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
# Line 1168  Line 1633 
1633                                  const uint32_t fcode,                                  const uint32_t fcode,
1634                                  const uint32_t bcode,                                  const uint32_t bcode,
1635                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1636                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1637                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1638                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1639                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1640                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1641                                    SearchData * const fData)
1642    
1643  {  {
 /* 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". */  
1644    
1645          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
   
1646          int iDirection, i, j;          int iDirection, i, j;
1647          int32_t iMinSAD = 256*4096;          SearchData bData;
         VECTOR currentMV[3];  
         SearchData fData, bData;  
1648    
1649            *(bData.iMinSAD = fData->iMinSAD) = 4096*256;
1650            bData.Cur = fData->Cur;
1651            fData->iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;
1652            bData.currentMV = fData->currentMV + 1; bData.currentQMV = fData->currentQMV + 1;
1653            bData.lambda16 = fData->lambda16;
1654            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1655    
1656            bData.bRef = fData->Ref = f_Ref + (x + y * iEdgedWidth) * 16;
1657            bData.bRefH = fData->RefH = f_RefH + (x + y * iEdgedWidth) * 16;
1658            bData.bRefV = fData->RefV = f_RefV + (x + y * iEdgedWidth) * 16;
1659            bData.bRefHV = fData->RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;
1660            bData.Ref = fData->bRef = b_Ref + (x + y * iEdgedWidth) * 16;
1661            bData.RefH = fData->bRefH = b_RefH + (x + y * iEdgedWidth) * 16;
1662            bData.RefV = fData->bRefV = b_RefV + (x + y * iEdgedWidth) * 16;
1663            bData.RefHV = fData->bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;
1664            bData.RefQ = fData->RefQ;
1665            fData->qpel_precision = bData.qpel_precision = 0; bData.qpel = fData->qpel;
1666            bData.rounding = 0;
1667    
1668            bData.bpredMV = fData->predMV = *f_predMV;
1669            fData->bpredMV = bData.predMV = *b_predMV;
1670    
1671            fData->currentMV[0] = fData->currentMV[2];
1672            get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode - pParam->m_quarterpel);
1673            get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode - pParam->m_quarterpel);
1674    
1675            if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1676            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dx;
1677            if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dy;
1678            if (fData->currentMV[0].y < fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1679    
1680            if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1681            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dx;
1682            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dy;
1683            if (fData->currentMV[1].y < bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1684    
1685          fData.iMinSAD = bData.iMinSAD = &iMinSAD;          CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
   
         fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;  
         fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;  
         fData.currentMV = currentMV; bData.currentMV = currentMV + 1;  
         fData.iQuant = bData.iQuant = iQuant;  
         fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;  
   
   
         bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  
         bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;  
         bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;  
         bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;  
         bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;  
         bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;  
         bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;  
         bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;  
   
         bData.bpredMV = fData.predMV = *f_predMV;  
         fData.bpredMV = bData.predMV = *b_predMV;  
   
   
         currentMV[0] = pMB->mvs[0];  
         currentMV[1] = pMB->b_mvs[0];  
         get_range(&fData.min_dx, &fData.max_dx, &fData.min_dy, &fData.max_dy, x, y, 16, pParam->width, pParam->height, fcode);  
         get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode);  
   
         CheckCandidateInt(currentMV[0].x, currentMV[0].y, 255, &iDirection, &fData);  
1686    
1687  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)
1688    
1689          do {          do {
1690                  iDirection = 255;                  iDirection = 255;
1691                  // forward MV moves                  // forward MV moves
1692                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
1693    
1694                  CheckCandidateInt(i + 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1695                  CheckCandidateInt(i, j + 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1696                  CheckCandidateInt(i - 2, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1697                  CheckCandidateInt(i, j - 2, 0, &iDirection, &fData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
1698    
1699                  // backward MV moves                  // backward MV moves
1700                  i = currentMV[1].x; j = currentMV[1].y;                  i = fData->currentMV[1].x; j = fData->currentMV[1].y;
1701                  currentMV[2] = currentMV[0];                  fData->currentMV[2] = fData->currentMV[0];
1702                    CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1703                  CheckCandidateInt(i + 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1704                  CheckCandidateInt(i, j + 2, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
1705                  CheckCandidateInt(i - 2, j, 0, &iDirection, &bData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, &bData);
                 CheckCandidateInt(i, j - 2, 0, &iDirection, &bData);  
1706    
1707          } while (!(iDirection));          } while (!(iDirection));
1708    
1709  /* halfpel refinement. luckly we can use normal halfpel function for it */          if (fData->qpel) {
   
         if (MotionFlags & PMV_HALFPELREFINE16) {  
1710                  CheckCandidate = CheckCandidateInt;                  CheckCandidate = CheckCandidateInt;
1711                  HalfpelRefine(&fData);                  fData->qpel_precision = bData.qpel_precision = 1;
1712                  currentMV[2] = currentMV[0];                  get_range_qpel(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode);
1713                  HalfpelRefine(&bData);                  get_range_qpel(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode);
1714          }                  fData->currentQMV[2].x = fData->currentQMV[0].x = 2 * fData->currentMV[0].x;
1715                    fData->currentQMV[2].y = fData->currentQMV[0].y = 2 * fData->currentMV[0].y;
1716  // two bits are needed to code interpolate mode. we treat the bits just like they were vector's                  fData->currentQMV[1].x = 2 * fData->currentMV[1].x;
1717          iMinSAD +=  2 * lambda_vec16[iQuant];                  fData->currentQMV[1].y = 2 * fData->currentMV[1].y;
1718          if (iMinSAD < *best_sad) {                  SubpelRefine(fData);
1719                  *best_sad = iMinSAD;                  fData->currentQMV[2] = fData->currentQMV[0];
1720                  pMB->mvs[0] = currentMV[0];                  SubpelRefine(&bData);
1721                  pMB->b_mvs[0] = currentMV[1];          }
1722    
1723            *fData->iMinSAD +=  2 * fData->lambda16; // two bits are needed to code interpolate mode.
1724    
1725            if (*fData->iMinSAD < *best_sad) {
1726                    *best_sad = *fData->iMinSAD;
1727                    pMB->mvs[0] = fData->currentMV[0];
1728                    pMB->b_mvs[0] = fData->currentMV[1];
1729                  pMB->mode = MODE_INTERPOLATE;                  pMB->mode = MODE_INTERPOLATE;
1730                    if (fData->qpel) {
1731                            pMB->qmvs[0] = fData->currentQMV[0];
1732                            pMB->b_qmvs[0] = fData->currentQMV[1];
1733                            pMB->pmvs[1].x = pMB->qmvs[0].x - f_predMV->x;
1734                            pMB->pmvs[1].y = pMB->qmvs[0].y - f_predMV->y;
1735                            pMB->pmvs[0].x = pMB->b_qmvs[0].x - b_predMV->x;
1736                            pMB->pmvs[0].y = pMB->b_qmvs[0].y - b_predMV->y;
1737                    } else {
1738                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;
1739                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;
1740                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;
1741                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;
1742          }          }
1743  }  }
1744    }
1745    
1746  void  void
1747  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
# Line 1277  Line 1755 
1755                                           const IMAGE * const f_refV,                                           const IMAGE * const f_refV,
1756                                           const IMAGE * const f_refHV,                                           const IMAGE * const f_refHV,
1757                                           // backward (future) reference                                           // backward (future) reference
1758                                           const MACROBLOCK * const b_mbs,                                           const FRAMEINFO * const b_reference,
1759                                           const IMAGE * const b_ref,                                           const IMAGE * const b_ref,
1760                                           const IMAGE * const b_refH,                                           const IMAGE * const b_refH,
1761                                           const IMAGE * const b_refV,                                           const IMAGE * const b_refV,
# Line 1287  Line 1765 
1765          int32_t best_sad, skip_sad;          int32_t best_sad, skip_sad;
1766          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;
1767          static const VECTOR zeroMV={0,0};          static const VECTOR zeroMV={0,0};
1768            const MACROBLOCK * const b_mbs = b_reference->mbs;
1769    
1770          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
1771    
1772          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1773          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
1774            uint8_t * qimage;
1775    
1776          // note: i==horizontal, j==vertical  // some pre-inintialized data for the rest of the search
1777    
1778            SearchData Data;
1779            int32_t iMinSAD;
1780            VECTOR currentMV[3];
1781            VECTOR currentQMV[3];
1782            memset(&Data, 0, sizeof(SearchData));
1783            Data.iEdgedWidth = pParam->edged_width;
1784            Data.currentMV = currentMV; Data.currentQMV = currentQMV;
1785            Data.iMinSAD = &iMinSAD;
1786            Data.lambda16 = lambda_vec16[frame->quant] + 2;
1787            Data.qpel = pParam->m_quarterpel;
1788            Data.rounding = 0;
1789    
1790            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
1791                    return; // allocate some mem for qpel interpolated blocks
1792                                      // somehow this is dirty since I think we shouldn't use malloc outside
1793                                      // encoder_create() - so please fix me!
1794            Data.RefQ = qimage;
1795    
1796            // note: i==horizontal, j==vertical
1797          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
1798    
1799                  f_predMV = b_predMV = zeroMV;   /* prediction is reset at left boundary */                  f_predMV = b_predMV = zeroMV;   /* prediction is reset at left boundary */
# Line 1303  Line 1802 
1802                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;
1803                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;
1804    
1805  /* 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 */
1806                            if (b_reference->coding_type != S_VOP)
1807                          if (b_mb->mode == MODE_NOT_CODED) {                          if (b_mb->mode == MODE_NOT_CODED) {
1808                                  pMB->mode = MODE_NOT_CODED;                                  pMB->mode = MODE_NOT_CODED;
1809                                  continue;                                  continue;
1810                          }                          }
1811    
1812                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
1813                            pMB->quant = frame->quant;
1814    
1815  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
1816          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
1817                            skip_sad = SearchDirect(f_ref, f_refH->y, f_refV->y, f_refHV->y,
1818                          skip_sad = SearchDirect(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,
                                                                         b_ref->y, b_refH->y, b_refV->y, b_refHV->y,  
1819                                                                          &frame->image,                                                                          &frame->image,
1820                                                                          i, j,                                                                          i, j,
1821                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
1822                                                                          TRB, TRD,                                                                          TRB, TRD,
1823                                                                          pParam,                                                                          pParam,
1824                                                                          pMB, b_mb,                                                                          pMB, b_mb,
1825                                                                          &best_sad);                                                                          &best_sad,
1826                                                                            &Data);
1827    
                         if (!(frame->global_flags & XVID_HALFPEL)) best_sad = skip_sad = 256*4096;  
                         else  
1828                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                                  if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1829    
 //                      best_sad = 256*4096; //uncomment to disable Directsearch.  
 //      To disable any other mode, just comment the function call  
   
1830                          // forward search                          // forward search
1831                          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,
1832                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1833                                                  frame->motion_flags,                                                  frame->motion_flags,
1834                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
1835                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
1836                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
1837    
1838                          // backward search                          // backward search
1839                          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,
1840                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1841                                                  frame->motion_flags,                                                  frame->motion_flags,
1842                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
1843                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
1844                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
1845    
1846                          // 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
1847    
# Line 1354  Line 1851 
1851                                                  i, j,                                                  i, j,
1852                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
1853                                                  frame->motion_flags,                                                  frame->motion_flags,
1854                                                  frame->quant, pParam,                                                  pParam,
1855                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
1856                                                  pMB, &best_sad);                                                  pMB, &best_sad,
1857                                                    &Data);
1858    
1859                          switch (pMB->mode) {                          switch (pMB->mode) {
1860                                  case MODE_FORWARD:                                  case MODE_FORWARD:
1861                                          f_count++;                                          f_count++;
1862                                          f_predMV = pMB->mvs[0];                                          if (pParam->m_quarterpel) f_predMV = pMB->qmvs[0];
1863                                            else f_predMV = pMB->mvs[0];
1864                                          break;                                          break;
1865                                  case MODE_BACKWARD:                                  case MODE_BACKWARD:
1866                                          b_count++;                                          b_count++;
1867                                          b_predMV = pMB->b_mvs[0];                                          if (pParam->m_quarterpel) b_predMV = pMB->b_qmvs[0];
1868                                            else b_predMV = pMB->b_mvs[0];
1869                                          break;                                          break;
1870                                  case MODE_INTERPOLATE:                                  case MODE_INTERPOLATE:
1871                                          i_count++;                                          i_count++;
1872                                            if (pParam->m_quarterpel) {
1873                                                    f_predMV = pMB->qmvs[0];
1874                                                    b_predMV = pMB->b_qmvs[0];
1875                                            } else {
1876                                          f_predMV = pMB->mvs[0];                                          f_predMV = pMB->mvs[0];
1877                                          b_predMV = pMB->b_mvs[0];                                          b_predMV = pMB->b_mvs[0];
1878                                            }
1879                                          break;                                          break;
1880                                  case MODE_DIRECT:                                  case MODE_DIRECT:
1881                                  case MODE_DIRECT_NO4V:                                  case MODE_DIRECT_NO4V:
1882                                          d_count++;                                          d_count++;
                                         break;  
1883                                  default:                                  default:
1884                                          break;                                          break;
1885                          }                          }
1886                  }                  }
1887          }          }
1888            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);  
   
1889  }  }
1890    
1891  /* Hinted ME starts here */  /* Hinted ME starts here */
1892    
 static __inline void  
 Search8hinted(  const SearchData * const OldData,  
                                 const int x, const int y,  
                                 const uint32_t MotionFlags,  
                                 const MBParam * const pParam,  
                                 MACROBLOCK * const pMB,  
                                 const MACROBLOCK * const pMBs,  
                                 const int block)  
 {  
         SearchData Data;  
         MainSearchFunc *MainSearchPtr;  
   
         Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);  
         Data.iMinSAD = OldData->iMinSAD + 1 + block;  
         Data.currentMV = OldData->currentMV+1+block;  
         Data.iFcode = OldData->iFcode;  
         Data.iQuant = OldData->iQuant;  
   
         Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));  
         Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));  
         Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));  
         Data.RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));  
         Data.iEdgedWidth = pParam->edged_width;  
         Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));  
   
         CheckCandidate = CheckCandidate8;  
   
         if (block != 0)  
                 *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *  
                                                                 d_mv_bits(      Data.currentMV->x - Data.predMV.x,  
                                                                                         Data.currentMV->y - Data.predMV.y,  
                                                                                         Data.iFcode);  
   
   
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,  
                                 pParam->width, pParam->height, OldData->iFcode);  
   
         if (pMB->mode == MODE_INTER4V) {  
                 int dummy;  
                 CheckCandidate8(pMB->mvs[block].x, pMB->mvs[block].y, 0, &dummy, &Data); }  
   
         if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;  
                 else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;  
                         else MainSearchPtr = DiamondSearch;  
   
         (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);  
   
         if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);  
   
         pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;  
         pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;  
         pMB->mvs[block] = *(Data.currentMV);  
         pMB->sad8[block] =  4 * (*(Data.iMinSAD));  
 }  
   
   
1893  static void  static void
1894  SearchPhinted ( const uint8_t * const pRef,  SearchPhinted ( const IMAGE * const pRef,
1895                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
1896                                  const uint8_t * const pRefV,                                  const uint8_t * const pRefV,
1897                                  const uint8_t * const pRefHV,                                  const uint8_t * const pRefHV,
# Line 1455  Line 1900 
1900                                  const int y,                                  const int y,
1901                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1902                                  const uint32_t iQuant,                                  const uint32_t iQuant,
                                 const uint32_t iFcode,  
1903                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1904                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1905                                  int inter4v,                                  int inter4v,
1906                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
1907                                    SearchData * const Data)
1908  {  {
1909    
1910          const int32_t iEdgedWidth = pParam->edged_width;          int i, t;
   
         int i;  
         VECTOR currentMV[5];  
         int32_t iMinSAD[5];  
         int32_t temp[5];  
1911          MainSearchFunc * MainSearchPtr;          MainSearchFunc * MainSearchPtr;
         SearchData Data;  
1912    
1913          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,
1914          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,                                  pParam->width, pParam->height, Data->iFcode - pParam->m_quarterpel);
                                 pParam->width, pParam->height, iFcode);  
1915    
1916          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
1917          Data.iEdgedWidth = iEdgedWidth;          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1918          Data.currentMV = currentMV;          Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1919          Data.iMinSAD = iMinSAD;  
1920          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16;
1921          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
1922          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
1923          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
1924          Data.temp = temp;          Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1925          Data.iQuant = iQuant;          Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1926          Data.iFcode = iFcode;          Data->qpel_precision = 0;
1927    
1928          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
1929                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
1930                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
1931                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
1932                  Data.max_dy = EVEN(Data.max_dy);                  Data->max_dy = EVEN(Data->max_dy);
1933          }          }
1934            if (pParam->m_quarterpel) Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1935            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1936    
1937          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;          for(i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
1938    
1939          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
1940    
1941          if (inter4v)          if (inter4v || Data->chroma) CheckCandidate = CheckCandidate16;
                 CheckCandidate = CheckCandidate16;  
1942          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
1943    
   
1944          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);
1945          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);
1946          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->max_dx) pMB->mvs[0].x = Data->max_dx; // this is in case iFcode changed
1947          if (pMB->mvs[0].x < Data.min_dx) pMB->mvs[0].x = Data.min_dx;          if (pMB->mvs[0].x < Data->min_dx) pMB->mvs[0].x = Data->min_dx;
1948          if (pMB->mvs[0].y > Data.max_dy) pMB->mvs[0].y = Data.max_dy;          if (pMB->mvs[0].y > Data->max_dy) pMB->mvs[0].y = Data->max_dy;
1949          if (pMB->mvs[0].y < Data.min_dy) pMB->mvs[0].y = Data.min_dy;          if (pMB->mvs[0].y < Data->min_dy) pMB->mvs[0].y = Data->min_dy;
1950    
1951          CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);          (*CheckCandidate)(pMB->mvs[0].x, pMB->mvs[0].y, 0, &t, Data);
1952    
1953          if (pMB->mode == MODE_INTER4V)          if (pMB->mode == MODE_INTER4V)
1954                  for (i = 1; i < 4; i++) { // all four vectors will be used as four predictions for 16x16 search                  for (i = 1; i < 4; i++) { // all four vectors will be used as four predictions for 16x16 search
1955                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);
1956                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);
1957                          if (!(make_mask(pMB->mvs, i)))                          if (!(make_mask(pMB->mvs, i)))
1958                                  CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);                                  (*CheckCandidate)(pMB->mvs[i].x, pMB->mvs[i].y, 0, &t, Data);
1959                  }                  }
1960    
1961          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1526  Line 1964 
1964                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1965                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1966    
1967          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1968    
1969          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (MotionFlags & PMV_HALFPELREFINE16) SubpelRefine(Data);
1970    
1971            for(i = 0; i < 5; i++) {
1972                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1973                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1974            }
1975    
1976            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1977                    get_range_qpel(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1978                                    pParam->width, pParam->height, Data->iFcode);
1979                    Data->qpel_precision = 1;
1980                    SubpelRefine(Data);
1981            }
1982    
1983            if (inter4v) {
1984                    SearchData Data8;
1985                    Data8.iFcode = Data->iFcode;
1986                    Data8.lambda8 = Data->lambda8;
1987                    Data8.iEdgedWidth = Data->iEdgedWidth;
1988                    Data8.RefQ = Data->RefQ;
1989                    Data8.qpel = Data->qpel;
1990                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1991                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1992                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1993                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1994    
1995                    if (Data->chroma) {
1996                            int sumx, sumy, dx, dy;
1997    
1998                            if(pParam->m_quarterpel) {
1999                                    sumx= pMB->qmvs[0].x/2 + pMB->qmvs[1].x/2 + pMB->qmvs[2].x/2 + pMB->qmvs[3].x/2;
2000                                    sumy = pMB->qmvs[0].y/2 + pMB->qmvs[1].y/2 + pMB->qmvs[2].y/2 + pMB->qmvs[3].y/2;
2001                            } else {
2002                                    sumx = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
2003                                    sumy = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
2004                            }
2005                            dx = (sumx >> 3) + roundtab_76[sumx & 0xf];
2006                            dy = (sumy >> 3) + roundtab_76[sumy & 0xf];
2007    
2008          if (inter4v)                          Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);
2009                  for(i = 0; i < 4; i++)                  }
2010                          Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);          }
2011    
2012          if (!(inter4v) ||          if (!(inter4v) ||
2013                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3] +
2014                                                            Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
2015  // INTER MODE  // INTER MODE
   
2016                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
2017                  pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
2018                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
2019    
2020                    pMB->qmvs[0] = pMB->qmvs[1]
2021                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
2022    
2023                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
2024                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
2025    
2026                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
2027                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predMV.x;
2028                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predMV.y;
2029          } else {          } else {
2030  // INTER4V MODE; all other things are already set in Search8hinted                          pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
2031                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
2032                    }
2033            } else {
2034    // INTER4V MODE; all other things are already set in Search8
2035                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
2036                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3]
2037                                                    + Data->iMinSAD[4] + IMV16X16 * iQuant;
2038          }          }
2039    
2040  }  }
# Line 1568  Line 2052 
2052          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
2053    
2054          uint32_t x, y;          uint32_t x, y;
2055            uint8_t * qimage;
2056            int32_t temp[5], quant = current->quant;
2057            int32_t iMinSAD[5];
2058            VECTOR currentMV[5], currentQMV[5];
2059            SearchData Data;
2060            Data.iEdgedWidth = pParam->edged_width;
2061            Data.currentMV = currentMV;
2062            Data.currentQMV = currentQMV;
2063            Data.iMinSAD = iMinSAD;
2064            Data.temp = temp;
2065            Data.iFcode = current->fcode;
2066            Data.rounding = pParam->m_rounding_type;
2067            Data.qpel = pParam->m_quarterpel;
2068            Data.chroma = current->global_flags & XVID_ME_COLOUR;
2069    
2070            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
2071                    return; // allocate some mem for qpel interpolated blocks
2072                                      // somehow this is dirty since I think we shouldn't use malloc outside
2073                                      // encoder_create() - so please fix me!
2074    
2075            Data.RefQ = qimage;
2076    
2077          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
2078    
2079          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
2080                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
                         int32_t sad00;  
2081    
2082                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2083    
# Line 1583  Line 2087 
2087                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
2088                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
2089                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant; }
2090                            else {
2091                                    if (pMB->dquant != NO_CHANGE) {
2092                                            quant += DQtab[pMB->dquant];
2093                                            if (quant > 31) quant = 31;
2094                                            else if (quant < 1) quant = 1;
2095                                    }
2096                                    pMB->quant = quant;
2097                            }
2098    
2099                          if (pMB->dquant == NO_CHANGE) //no skip otherwise, anyway                          SearchPhinted(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
2100                                  sad00 = pMB->sad16                                                          y, current->motion_flags, pMB->quant,
2101                                          = sad16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
2102                                                                  pRef->y + (x + y * pParam->edged_width) * 16,                                                          &Data);
                                                                 pParam->edged_width, 256*4096 );  
                         else sad00 = 256*4096;  
2103    
2104                    }
2105            }
2106            free(qimage);
2107    }
2108    
2109  //initial skip decision  static __inline int
2110    MEanalyzeMB (   const uint8_t * const pRef,
2111                                    const uint8_t * const pCur,
2112                                    const int x,
2113                                    const int y,
2114                                    const MBParam * const pParam,
2115                                    const MACROBLOCK * const pMBs,
2116                                    MACROBLOCK * const pMB,
2117                                    SearchData * const Data)
2118    {
2119    
2120                          if ( (pMB->dquant == NO_CHANGE) && (sad00 <= MAX_SAD00_FOR_SKIP * pMB->quant)          int i = 255, mask;
2121                                  && ( //(pMB->mode == MODE_NOT_CODED) ||          VECTOR pmv[3];
2122                                          (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant) )) ) {          *(Data->iMinSAD) = MV_MAX_ERROR;
2123                                  if (sad00 < pMB->quant * INITIAL_SKIP_THRESH) {  
2124                                          SkipMacroblockP(pMB, sad00);          //median is only used as prediction. it doesn't have to be real
2125                                          continue; } //skipped          if (x == 1 && y == 1) Data->predMV.x = Data->predMV.y = 0;
2126            else
2127                    if (x == 1) //left macroblock does not have any vector now
2128                            Data->predMV = (pMB - pParam->mb_width)->mvs[0]; // top instead of median
2129                    else if (y == 1) // top macroblock don't have it's vector
2130                            Data->predMV = (pMB - 1)->mvs[0]; // left instead of median
2131                            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); //else median
2132    
2133            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2134                                    pParam->width, pParam->height, Data->iFcode - pParam->m_quarterpel);
2135    
2136            Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
2137            Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
2138    
2139            pmv[1].x = EVEN(pMB->mvs[0].x);
2140            pmv[1].y = EVEN(pMB->mvs[0].y);
2141            pmv[2].x = EVEN(Data->predMV.x);
2142            pmv[2].y = EVEN(Data->predMV.y);
2143            pmv[0].x = pmv[0].y = 0;
2144    
2145            (*CheckCandidate)(0, 0, 255, &i, Data);
2146    
2147    //early skip for 0,0
2148            if (*Data->iMinSAD < MAX_SAD00_FOR_SKIP * 4) {
2149                    pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
2150                    pMB->mode = MODE_NOT_CODED;
2151                    return 0;
2152                          }                          }
                         else sad00 = 256*4096;  
2153    
2154                          if (pMB->mode == MODE_NOT_CODED)          if (!(mask = make_mask(pmv, 1)))
2155                                  SearchP(        pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                  (*CheckCandidate)(pmv[1].x, pmv[1].y, mask, &i, Data);
2156                                                          y, current->motion_flags, pMB->quant,          if (!(mask = make_mask(pmv, 2)))
2157                                                          current->fcode, pParam, pMBs, reference->mbs,                  (*CheckCandidate)(pmv[2].x, pmv[2].y, mask, &i, Data);
2158                                                          current->global_flags & XVID_INTER4V, pMB);  
2159            if (*Data->iMinSAD > MAX_SAD00_FOR_SKIP * 4) // diamond only if needed
2160                    DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
2161    
2162            pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
2163            pMB->mode = MODE_INTER;
2164            return *(Data->iMinSAD);
2165    }
2166    
2167    #define INTRA_THRESH    1350
2168    #define INTER_THRESH    1200
2169    
2170    
2171    int
2172    MEanalysis(     const IMAGE * const pRef,
2173                            FRAMEINFO * const Current,
2174                            MBParam * const pParam,
2175                            int maxIntra, //maximum number if non-I frames
2176                            int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame
2177                            int bCount) // number if B frames in a row
2178    {
2179            uint32_t x, y, intra = 0;
2180            int sSAD = 0;
2181            MACROBLOCK * const pMBs = Current->mbs;
2182            const IMAGE * const pCurrent = &Current->image;
2183            int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH;
2184    
2185            VECTOR currentMV;
2186            int32_t iMinSAD;
2187            SearchData Data;
2188            Data.iEdgedWidth = pParam->edged_width;
2189            Data.currentMV = &currentMV;
2190            Data.iMinSAD = &iMinSAD;
2191            Data.iFcode = Current->fcode;
2192            CheckCandidate = CheckCandidate16no4vI;
2193    
2194            if (intraCount < 10) // we're right after an I frame
2195                    IntraThresh += 4 * (intraCount - 10) * (intraCount - 10);
2196                          else                          else
2197                                  SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                  if ( 5*(maxIntra - intraCount) < maxIntra) // we're close to maximum. 2 sec when max is 10 sec
2198                                                          y, current->motion_flags, pMB->quant,                          IntraThresh -= (IntraThresh * (maxIntra - 5*(maxIntra - intraCount)))/maxIntra;
                                                         current->fcode, pParam, pMBs,  
                                                         current->global_flags & XVID_INTER4V, pMB);  
2199    
 /* final skip decision, a.k.a. "the vector you found, really that good?" */  
                         if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)  
                                 if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)  
                                 SkipMacroblockP(pMB, sad00);  
2200    
2201            InterThresh += 400 * (1 - bCount);
2202            if (InterThresh < 200) InterThresh = 200;
2203    
2204            if (sadInit) (*sadInit) ();
2205    
2206            for (y = 1; y < pParam->mb_height-1; y++) {
2207                    for (x = 1; x < pParam->mb_width-1; x++) {
2208                            int sad, dev;
2209                            MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2210    
2211                            sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
2212                                                                    pParam, pMBs, pMB, &Data);
2213    
2214                            if (sad > IntraThresh) {
2215                                    dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
2216                                                              pParam->edged_width);
2217                                    if (dev + IntraThresh < sad) {
2218                                            pMB->mode = MODE_INTRA;
2219                                            if (++intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame
2220                                    }
2221                            }
2222                            sSAD += sad;
2223                    }
2224            }
2225            sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2226            if (sSAD > InterThresh ) return 1; //P frame
2227            emms();
2228            return 0; // B frame
2229    
2230    }
2231    
2232    static void
2233    CheckGMC(int x, int y, const int dir, int * iDirection,
2234                    const MACROBLOCK * const pMBs, uint32_t * bestcount, VECTOR * GMC,
2235                    const MBParam * const pParam)
2236    {
2237            uint32_t mx, my, a, count = 0;
2238    
2239            for (my = 1; my < pParam->mb_height-1; my++)
2240                    for (mx = 1; mx < pParam->mb_width-1; mx++) {
2241                            VECTOR mv;
2242                            const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2243                            if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED) continue;
2244                            mv = pMB->mvs[0];
2245                            a = ABS(mv.x - x) + ABS(mv.y - y);
2246                            if (a < 6) count += 6 - a;
2247                  }                  }
2248    
2249            if (count > *bestcount) {
2250                    *bestcount = count;
2251                    *iDirection = dir;
2252                    GMC->x = x; GMC->y = y;
2253          }          }
2254  }  }
2255    
2256    
2257    static VECTOR
2258    GlobalMotionEst(const MACROBLOCK * const pMBs, const MBParam * const pParam, const uint32_t iFcode)
2259    {
2260    
2261            uint32_t count, bestcount = 0;
2262            int x, y;
2263            VECTOR gmc = {0,0};
2264            int step, min_x, max_x, min_y, max_y;
2265            uint32_t mx, my;
2266            int iDirection, bDirection;
2267    
2268            min_x = min_y = -32<<iFcode;
2269            max_x = max_y = 32<<iFcode;
2270    
2271    //step1: let's find a rough camera panning
2272            for (step = 32; step >= 2; step /= 2) {
2273                    bestcount = 0;
2274                    for (y = min_y; y <= max_y; y += step)
2275                            for (x = min_x ; x <= max_x; x += step) {
2276                                    count = 0;
2277                                    //for all macroblocks
2278                                    for (my = 1; my < pParam->mb_height-1; my++)
2279                                            for (mx = 1; mx < pParam->mb_width-1; mx++) {
2280                                                    const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2281                                                    VECTOR mv;
2282    
2283                                                    if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
2284                                                            continue;
2285    
2286                                                    mv = pMB->mvs[0];
2287                                                    if ( ABS(mv.x - x) <= step && ABS(mv.y - y) <= step )   /* GMC translation is always halfpel-res */
2288                                                            count++;
2289                                            }
2290                                    if (count >= bestcount) { bestcount = count; gmc.x = x; gmc.y = y; }
2291                            }
2292                    min_x = gmc.x - step;
2293                    max_x = gmc.x + step;
2294                    min_y = gmc.y - step;
2295                    max_y = gmc.y + step;
2296    
2297            }
2298    
2299            if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10)
2300                    gmc.x = gmc.y = 0; //no camara pan, no GMC
2301    
2302    // step2: let's refine camera panning using gradiend-descent approach.
2303    // TODO: more warping points may be evaluated here (like in interpolate mode search - two vectors in one diamond)
2304            bestcount = 0;
2305            CheckGMC(gmc.x, gmc.y, 255, &iDirection, pMBs, &bestcount, &gmc, pParam);
2306            do {
2307                    x = gmc.x; y = gmc.y;
2308                    bDirection = iDirection; iDirection = 0;
2309                    if (bDirection & 1) CheckGMC(x - 1, y, 1+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2310                    if (bDirection & 2) CheckGMC(x + 1, y, 2+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2311                    if (bDirection & 4) CheckGMC(x, y - 1, 1+2+4, &iDirection, pMBs, &bestcount, &gmc, pParam);
2312                    if (bDirection & 8) CheckGMC(x, y + 1, 1+2+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2313    
2314            } while (iDirection);
2315    
2316            if (pParam->m_quarterpel) {
2317                    gmc.x *= 2;
2318                    gmc.y *= 2;     /* we store the halfpel value as pseudo-qpel to make comparison easier */
2319            }
2320    
2321            return gmc;
2322    }

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

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