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

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

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

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

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

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