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

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

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