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

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

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