[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 675, Sun Nov 24 16:38:11 2002 UTC
# Line 37  Line 37 
37  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
38  #include "../global.h"  #include "../global.h"
39  #include "../utils/timer.h"  #include "../utils/timer.h"
40    #include "../image/interpolate8x8.h"
41  #include "motion_est.h"  #include "motion_est.h"
42  #include "motion.h"  #include "motion.h"
43  #include "sad.h"  #include "sad.h"
# Line 46  Line 47 
47  #define FINAL_SKIP_THRESH       (50)  #define FINAL_SKIP_THRESH       (50)
48  #define MAX_SAD00_FOR_SKIP      (20)  #define MAX_SAD00_FOR_SKIP      (20)
49  #define MAX_CHROMA_SAD_FOR_SKIP (22)  #define MAX_CHROMA_SAD_FOR_SKIP (22)
50  #define SKIP_THRESH_B (25)  #define SKIP_THRESH_B (15)
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 ); }
# 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            switch (((dx & 1) << 1) + (dy & 1))     { // ((dx%2)?2:0)+((dy%2)?1:0)
90                    case 0:
91                            sad = sad8(data->CurU, data->RefCU + (dy/2) * (data->iEdgedWidth/2) + dx/2, data->iEdgedWidth/2);
92                            sad += sad8(data->CurV, data->RefCV + (dy/2) * (data->iEdgedWidth/2) + dx/2, data->iEdgedWidth/2);
93                            break;
94                    case 1:
95                            dx = dx / 2; dy = (dy - 1) / 2;
96                            sad = sad8bi(data->CurU, data->RefCU + dy * (data->iEdgedWidth/2) + dx, data->RefCU + (dy+1) * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2);
97                            sad += sad8bi(data->CurV, data->RefCV + dy * (data->iEdgedWidth/2) + dx, data->RefCV + (dy+1) * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2);
98                            break;
99                    case 2:
100                            dx = (dx - 1) / 2; dy = dy / 2;
101                            sad = sad8bi(data->CurU, data->RefCU + dy * (data->iEdgedWidth/2) + dx, data->RefCU + dy * (data->iEdgedWidth/2) + dx+1, data->iEdgedWidth/2);
102                            sad += sad8bi(data->CurV, data->RefCV + dy * (data->iEdgedWidth/2) + dx, data->RefCV + dy * (data->iEdgedWidth/2) + dx+1, data->iEdgedWidth/2);
103                            break;
104                    default:
105                            dx = (dx - 1) / 2; dy = (dy - 1) / 2;
106                            interpolate8x8_halfpel_hv(data->RefQ,
107                                                                             data->RefCU + dy * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2,
108                                                                             data->rounding);
109                            sad = sad8(data->CurU, data->RefQ, data->iEdgedWidth/2);
110                            interpolate8x8_halfpel_hv(data->RefQ,
111                                                                             data->RefCV + dy * (data->iEdgedWidth/2) + dx, data->iEdgedWidth/2,
112                                                                             data->rounding);
113                            sad += sad8(data->CurV, data->RefQ, data->iEdgedWidth/2);
114                            break;
115            }
116            return sad;
117    }
118    
119    static __inline const uint8_t *
120    GetReference(const int x, const int y, const int dir, const SearchData * const data)
121    {
122    //      dir : 0 = forward, 1 = backward
123            switch ( (dir << 2) | ((x&1)<<1) | (y&1) ) {
124                    case 0 : return data->Ref + x/2 + (y/2)*(data->iEdgedWidth);
125                    case 1 : return data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth);
126                    case 2 : return data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth);
127                    case 3 : return data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth);
128                    case 4 : return data->bRef + x/2 + (y/2)*(data->iEdgedWidth);
129                    case 5 : return data->bRefV + x/2 + ((y-1)/2)*(data->iEdgedWidth);
130                    case 6 : return data->bRefH + (x-1)/2 + (y/2)*(data->iEdgedWidth);
131                    default : return data->bRefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth);
132    
133            }
134    }
135    
136    static uint8_t *
137    Interpolate8x8qpel(const int x, const int y, const int block, const int dir, const SearchData * const data)
138    {
139    // create or find a qpel-precision reference picture; return pointer to it
140            uint8_t * Reference = (uint8_t *)data->RefQ + 16*dir;
141            const int32_t iEdgedWidth = data->iEdgedWidth;
142            const uint32_t rounding = data->rounding;
143            const int halfpel_x = x/2;
144            const int halfpel_y = y/2;
145            const uint8_t *ref1, *ref2, *ref3, *ref4;
146    
147            ref1 = GetReference(halfpel_x, halfpel_y, dir, data); // this reference is used in all cases
148            ref1 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
149            switch( ((x&1)<<1) + (y&1) ) {
150            case 0: // pure halfpel position
151                    Reference = (uint8_t *) GetReference(halfpel_x, halfpel_y, dir, data);
152                    Reference += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
153                    break;
154    
155            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
156                    ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);
157                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
158                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
159                    break;
160    
161            case 2: // x qpel, y halfpel - left or right during qpel refinement
162                    ref2 = GetReference(x - halfpel_x, halfpel_y, dir, data);
163                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
164                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
165                    break;
166    
167            default: // x and y in qpel resolution - the "corners" (top left/right and
168                             // bottom left/right) during qpel refinement
169                    ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);
170                    ref3 = GetReference(x - halfpel_x, halfpel_y, dir, data);
171                    ref4 = GetReference(x - halfpel_x, y - halfpel_y, dir, data);
172                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
173                    ref3 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
174                    ref4 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
175                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
176                    break;
177            }
178            return Reference;
179    }
180    
181    static uint8_t *
182    Interpolate16x16qpel(const int x, const int y, const int dir, const SearchData * const data)
183    {
184    // create or find a qpel-precision reference picture; return pointer to it
185            uint8_t * Reference = (uint8_t *)data->RefQ + 16*dir;
186            const int32_t iEdgedWidth = data->iEdgedWidth;
187            const uint32_t rounding = data->rounding;
188            const int halfpel_x = x/2;
189            const int halfpel_y = y/2;
190            const uint8_t *ref1, *ref2, *ref3, *ref4;
191    
192            ref1 = GetReference(halfpel_x, halfpel_y, dir, data); // this reference is used in all cases
193            switch( ((x&1)<<1) + (y&1) ) {
194            case 0: // pure halfpel position
195                    return (uint8_t *) GetReference(halfpel_x, halfpel_y, dir, data);
196            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
197                    ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);
198                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
199                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
200                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
201                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
202                    break;
203    
204            case 2: // x qpel, y halfpel - left or right during qpel refinement
205                    ref2 = GetReference(x - halfpel_x, halfpel_y, dir, data);
206                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
207                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
208                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
209                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
210                    break;
211    
212            default: // x and y in qpel resolution - the "corners" (top left/right and
213                             // bottom left/right) during qpel refinement
214                    ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data);
215                    ref3 = GetReference(x - halfpel_x, halfpel_y, dir, data);
216                    ref4 = GetReference(x - halfpel_x, y - halfpel_y, dir, data);
217                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
218                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
219                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
220                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
221                    break;
222            }
223            return Reference;
224    }
225    
226  /* CHECK_CANDIATE FUNCTIONS START */  /* CHECK_CANDIATE FUNCTIONS START */
227    
228  static void  static void
229  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)
230  {  {
231          int32_t * const sad = data->temp;          int t, xc, yc;
         int t;  
232          const uint8_t * Reference;          const uint8_t * Reference;
233            VECTOR * current;
234    
235          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
236                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
237    
238            if (data->qpel_precision) { // x and y are in 1/4 precision
239                    Reference = Interpolate16x16qpel(x, y, 0, data);
240                    t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
241                    xc = x/2; yc = y/2; //for chroma sad
242                    current = data->currentQMV;
243            } else {
244          switch ( ((x&1)<<1) + (y&1) ) {          switch ( ((x&1)<<1) + (y&1) ) {
245                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;
246                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;
247                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;
248                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;
249          }          }
250                    if (data->qpel) t = d_mv_bits(2*x - data->predMV.x, 2*y - data->predMV.y, data->iFcode);
251                    else t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
252                    current = data->currentMV;
253                    xc = x; yc = y;
254            }
255    
256          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, sad+1);          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
257    
258          t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          data->temp[0] += (data->lambda16 * t * data->temp[0])/1000;
259          data->temp[0] += lambda_vec16[data->iQuant] * t;          data->temp[1] += (data->lambda8 * t * (data->temp[1] + NEIGH_8X8_BIAS))/100;
260          data->temp[1] += lambda_vec8[data->iQuant] * t;  
261            if (data->chroma) data->temp[0] += ChromaSAD(xc, yc, data);
262    
263          if (data->temp[0] < data->iMinSAD[0]) {          if (data->temp[0] < data->iMinSAD[0]) {
264                  data->iMinSAD[0] = data->temp[0];                  data->iMinSAD[0] = data->temp[0];
265                  data->currentMV[0].x = x; data->currentMV[0].y = y;                  current[0].x = x; current[0].y = y;
266                  *dir = Direction; }                  *dir = Direction; }
267    
268          if (data->temp[1] < data->iMinSAD[1]) {          if (data->temp[1] < data->iMinSAD[1]) {
269                  data->iMinSAD[1] = data->temp[1]; data->currentMV[1].x = x; data->currentMV[1].y = y; }                  data->iMinSAD[1] = data->temp[1]; current[1].x = x; current[1].y= y; }
270          if (data->temp[2] < data->iMinSAD[2]) {          if (data->temp[2] < data->iMinSAD[2]) {
271                  data->iMinSAD[2] = data->temp[2]; data->currentMV[2].x = x; data->currentMV[2].y = y; }                  data->iMinSAD[2] = data->temp[2]; current[2].x = x; current[2].y = y; }
272          if (data->temp[3] < data->iMinSAD[3]) {          if (data->temp[3] < data->iMinSAD[3]) {
273                  data->iMinSAD[3] = data->temp[3]; data->currentMV[3].x = x; data->currentMV[3].y = y; }                  data->iMinSAD[3] = data->temp[3]; current[3].x = x; current[3].y = y; }
274          if (data->temp[4] < data->iMinSAD[4]) {          if (data->temp[4] < data->iMinSAD[4]) {
275                  data->iMinSAD[4] = data->temp[4]; data->currentMV[4].x = x; data->currentMV[4].y = y; }                  data->iMinSAD[4] = data->temp[4]; current[4].x = x; current[4].y = y; }
276    
277  }  }
278    
# Line 125  Line 281 
281  {  {
282          int32_t sad;          int32_t sad;
283          const uint8_t * Reference;          const uint8_t * Reference;
284            int t;
285            VECTOR * current;
286    
287          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
288                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
289    
290          switch ( ((x&1)<<1) + (y&1) )          if (data->qpel_precision) { // x and y are in 1/4 precision
291          {                  Reference = Interpolate16x16qpel(x, y, 0, data);
292                    t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
293                    current = data->currentQMV;
294            } else {
295                    switch ( ((x&1)<<1) + (y&1) ) {
296                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;                  case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;
297                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;
298                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;                  case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;
299                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;
300          }          }
301                    if (data->qpel) t = d_mv_bits(2*x - data->predMV.x, 2*y - data->predMV.y, data->iFcode);
302                    else t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
303                    current = data->currentMV;
304            }
305    
306          sad = lambda_vec16[data->iQuant] *          sad = sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);
307                          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);  
308    
309          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
310                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
311                  data->currentMV[0].x = x; data->currentMV[0].y = y;                  current->x = x; current->y = y;
312                  *dir = Direction; }                  *dir = Direction; }
313  }  }
314    
315  static void  static void
316  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)
317  {  {
318    // maximum speed - for P/B/I decision
319          int32_t sad;          int32_t sad;
320    
321          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
322                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
323    
324          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),  
325                                          data->iEdgedWidth, 256*4096);                                          data->iEdgedWidth, 256*4096);
326    
327          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
# Line 172  Line 335 
335  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)
336  {  {
337          int32_t sad;          int32_t sad;
338          const int xb = data->currentMV[1].x;          int xb, yb, t;
         const int yb = data->currentMV[1].y;  
339          const uint8_t *ReferenceF, *ReferenceB;          const uint8_t *ReferenceF, *ReferenceB;
340            VECTOR *current;
341    
342          if (( xf > data->max_dx) || ( xf < data->min_dx)          if (( xf > data->max_dx) || ( xf < data->min_dx)
343                  || ( yf > data->max_dy) || (yf < data->min_dy)) return;                  || ( yf > data->max_dy) || (yf < data->min_dy)) return;
344    
345          switch ( ((xf&1)<<1) + (yf&1) ) {          if (data->qpel_precision) {
346                  case 0 : ReferenceF = data->Ref + xf/2 + (yf/2)*(data->iEdgedWidth); break;                  ReferenceF = Interpolate16x16qpel(xf, yf, 0, data);
347                  case 1 : ReferenceF = data->RefV + xf/2 + ((yf-1)/2)*(data->iEdgedWidth); break;                  xb = data->currentQMV[1].x; yb = data->currentQMV[1].y;
348                  case 2 : ReferenceF = data->RefH + (xf-1)/2 + (yf/2)*(data->iEdgedWidth); break;                  current = data->currentQMV;
349                  default : ReferenceF = data->RefHV + (xf-1)/2 + ((yf-1)/2)*(data->iEdgedWidth); break;                  ReferenceB = Interpolate16x16qpel(xb, yb, 1, data);
350          }                  t = d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode)
351                                     + d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode);
352          switch ( ((xb&1)<<1) + (yb&1) ) {          } else {
353                  case 0 : ReferenceB = data->bRef + xb/2 + (yb/2)*(data->iEdgedWidth); break;                  ReferenceF = Interpolate16x16qpel(2*xf, 2*yf, 0, data);
354                  case 1 : ReferenceB = data->bRefV + xb/2 + ((yb-1)/2)*(data->iEdgedWidth); break;                  xb = data->currentMV[1].x; yb = data->currentMV[1].y;
355                  case 2 : ReferenceB = data->bRefH + (xb-1)/2 + (yb/2)*(data->iEdgedWidth); break;                  ReferenceB = Interpolate16x16qpel(2*xb, 2*yb, 1, data);
356                  default : ReferenceB = data->bRefHV + (xb-1)/2 + ((yb-1)/2)*(data->iEdgedWidth); break;                  current = data->currentMV;
357                    if (data->qpel)
358                            t = d_mv_bits(2*xf - data->predMV.x, 2*yf - data->predMV.y, data->iFcode)
359                                             + d_mv_bits(2*xb - data->bpredMV.x, 2*yb - data->bpredMV.y, data->iFcode);
360                    else
361                            t = d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode)
362                                             + d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode);
363          }          }
364    
365          sad = lambda_vec16[data->iQuant] *          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
366                          ( d_mv_bits(xf - data->predMV.x, yf - data->predMV.y, data->iFcode) +          sad += (data->lambda16 * t * sad)/1000;
                           d_mv_bits(xb - data->bpredMV.x, yb - data->bpredMV.y, data->iFcode) );  
   
         sad += sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);  
367    
368          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
369                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
370                  data->currentMV->x = xf; data->currentMV->y = yf;                  current->x = xf; current->y = yf;
371                  *dir = Direction; }                  *dir = Direction; }
372  }  }
373    
374  static void  static void
375  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)
376  {  {
377          int32_t sad;          int32_t sad = 0;
378          int k;          int k;
379          const uint8_t *ReferenceF;          const uint8_t *ReferenceF;
380          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
# Line 216  Line 382 
382    
383          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
384    
         sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);  
   
385          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
386                  mvs.x = data->directmvF[k].x + x;                  mvs.x = data->directmvF[k].x + x;
387                  b_mvs.x = ((x == 0) ?                  b_mvs.x = ((x == 0) ?
# Line 234  Line 398 
398                          || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )                          || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )
399                          || ( 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;
400    
401                  switch ( ((mvs.x&1)<<1) + (mvs.y&1) ) {                  if (!data->qpel) {
402                          case 0 : ReferenceF = data->Ref + mvs.x/2 + (mvs.y/2)*(data->iEdgedWidth); break;                          mvs.x *= 2; mvs.y *= 2;
403                          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;  
404                  }                  }
405                    ReferenceF = Interpolate8x8qpel(mvs.x, mvs.y, k, 0, data);
406                    ReferenceB = Interpolate8x8qpel(b_mvs.x, b_mvs.y, k, 1, data);
407    
408                  sad += sad8bi(data->Cur + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),                  sad += sad8bi(data->Cur + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),
409                                                  ReferenceF + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),                                                  ReferenceF, ReferenceB,
                                                 ReferenceB + 8*(k&1) + 8*(k>>1)*(data->iEdgedWidth),  
410                                                  data->iEdgedWidth);                                                  data->iEdgedWidth);
411                  if (sad > *(data->iMinSAD)) return;                  if (sad > *(data->iMinSAD)) return;
412          }          }
413    
414            sad += (data->lambda16 * d_mv_bits(x, y, 1) * sad)/1000;
415    
416          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
417                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
418                  data->currentMV->x = x; data->currentMV->y = y;                  data->currentMV->x = x; data->currentMV->y = y;
# Line 269  Line 427 
427          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
428          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
429    
430          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);  
431    
432          mvs.x = data->directmvF[0].x + x;          mvs.x = data->directmvF[0].x + x;
433          b_mvs.x = ((x == 0) ?          b_mvs.x = ((x == 0) ?
# Line 288  Line 444 
444                  || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )                  || ( b_mvs.x > data->max_dx ) || ( b_mvs.x < data->min_dx )
445                  || ( 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;
446    
447          switch ( ((mvs.x&1)<<1) + (mvs.y&1) ) {          if (!data->qpel) {
448                  case 0 : ReferenceF = data->Ref + mvs.x/2 + (mvs.y/2)*(data->iEdgedWidth); break;                          mvs.x *= 2; mvs.y *= 2;
449                  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;  
450          }          }
451            ReferenceF = Interpolate16x16qpel(mvs.x, mvs.y, 0, data);
452            ReferenceB = Interpolate16x16qpel(b_mvs.x, b_mvs.y, 1, data);
453    
454          switch ( ((b_mvs.x&1)<<1) + (b_mvs.y&1) ) {          sad = sad16bi(data->Cur, ReferenceF, ReferenceB, data->iEdgedWidth);
455                  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) * 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);  
456    
457          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
458                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 313  Line 463 
463  static void  static void
464  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)
465  {  {
466          int32_t sad;          int32_t sad; int t;
467          const uint8_t * Reference;          const uint8_t * Reference;
468    
469          if (( x > data->max_dx) || ( x < data->min_dx)          if (( x > data->max_dx) || ( x < data->min_dx)
470                  || ( y > data->max_dy) || (y < data->min_dy)) return;                  || ( y > data->max_dy) || (y < data->min_dy)) return;
471    
472          switch ( ((x&1)<<1) + (y&1) )          if (data->qpel) Reference = Interpolate16x16qpel(x, y, 0, data);
473          {          else Reference = Interpolate16x16qpel(2*x, 2*y, 0, data);
                 case 0 : Reference = data->Ref + x/2 + (y/2)*(data->iEdgedWidth); break;  
                 case 1 : Reference = data->RefV + x/2 + ((y-1)/2)*(data->iEdgedWidth); break;  
                 case 2 : Reference = data->RefH + (x-1)/2 + (y/2)*(data->iEdgedWidth); break;  
                 default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;  
         }  
474    
475          sad = sad8(data->Cur, Reference, data->iEdgedWidth);          sad = sad8(data->Cur, Reference, data->iEdgedWidth);
476          sad += lambda_vec8[data->iQuant] * d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          if (data->qpel) t = d_mv_bits(2 * x - data->predMV.x, 2 * y - data->predMV.y, data->iFcode);
477            else t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
478    
479            sad += (data->lambda8 * t * (sad+NEIGH_8X8_BIAS))/100;
480    
481          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
482                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 485  Line 633 
633  /* 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 */
634    
635  static void  static void
636  HalfpelRefine(const SearchData * const data)  SubpelRefine(const SearchData * const data)
637  {  {
638  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a half-pel or q-pel refinement */
639            VECTOR backupMV;
         VECTOR backupMV = *(data->currentMV);  
640          int iDirection; //not needed          int iDirection; //not needed
641    
642            if (data->qpel_precision)
643                    backupMV = *(data->currentQMV);
644            else backupMV = *(data->currentMV);
645    
646          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);
647          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);          CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);
648          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);          CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);
# Line 517  Line 668 
668          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,          uint32_t sadC = sad8(current->u + x*8 + y*(iEdgedWidth/2)*8,
669                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                          reference->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);
670          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
671          sadC += sad8(current->v + x*8 + y*(iEdgedWidth/2)*8,          sadC += sad8(current->v + (x + y*(iEdgedWidth/2))*8,
672                                          reference->v + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2);                                          reference->v + (x + y*(iEdgedWidth/2))*8, iEdgedWidth/2);
673          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;          if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
674    
675          return 1;          return 1;
# Line 530  Line 681 
681          pMB->mode = MODE_NOT_CODED;          pMB->mode = MODE_NOT_CODED;
682          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;
683          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;
684    
685            pMB->qmvs[0].x = pMB->qmvs[1].x = pMB->qmvs[2].x = pMB->qmvs[3].x = 0;
686            pMB->qmvs[0].y = pMB->qmvs[1].y = pMB->qmvs[2].y = pMB->qmvs[3].y = 0;
687    
688          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;
689  }  }
690    
# Line 550  Line 705 
705    
706          uint32_t x, y;          uint32_t x, y;
707          uint32_t iIntra = 0;          uint32_t iIntra = 0;
708          int32_t InterBias;          int32_t InterBias, quant = current->quant, sad00;
709            uint8_t *qimage;
710    
711          // some pre-initialized thingies for SearchP          // some pre-initialized thingies for SearchP
712          int32_t temp[5];          int32_t temp[5];
713          VECTOR currentMV[5];          VECTOR currentMV[5];
714            VECTOR currentQMV[5];
715          int32_t iMinSAD[5];          int32_t iMinSAD[5];
716          SearchData Data;          SearchData Data;
717          Data.iEdgedWidth = pParam->edged_width;          Data.iEdgedWidth = pParam->edged_width;
718          Data.currentMV = currentMV;          Data.currentMV = currentMV;
719            Data.currentQMV = currentQMV;
720          Data.iMinSAD = iMinSAD;          Data.iMinSAD = iMinSAD;
721          Data.temp = temp;          Data.temp = temp;
722          Data.iFcode = current->fcode;          Data.iFcode = current->fcode;
723            Data.rounding = pParam->m_rounding_type;
724            Data.qpel = pParam->m_quarterpel;
725            Data.chroma = current->global_flags & XVID_ME_COLOUR;
726    
727            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
728                    return 1; // allocate some mem for qpel interpolated blocks
729                                      // somehow this is dirty since I think we shouldn't use malloc outside
730                                      // encoder_create() - so please fix me!
731            Data.RefQ = qimage;
732          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
733    
734          for (y = 0; y < pParam->mb_height; y++) {          for (y = 0; y < pParam->mb_height; y++) {
735                  for (x = 0; x < pParam->mb_width; x++)  {                  for (x = 0; x < pParam->mb_width; x++)  {
   
736                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
737                          int32_t sad00 =  pMB->sad16  
738                            pMB->sad16
739                                  = sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,                                  = sad16v(pCurrent->y + (x + y * pParam->edged_width) * 16,
740                                                          pRef->y + (x + y * pParam->edged_width) * 16,                                                          pRef->y + (x + y * pParam->edged_width) * 16,
741                                                          pParam->edged_width, pMB->sad8 );                                                          pParam->edged_width, pMB->sad8 );
742    
743                            if (Data.chroma) {
744                                    pMB->sad16 += sad8(pCurrent->u + x*8 + y*(pParam->edged_width/2)*8,
745                                                                    pRef->u + x*8 + y*(pParam->edged_width/2)*8, pParam->edged_width/2);
746    
747                                    pMB->sad16 += sad8(pCurrent->v + (x + y*(pParam->edged_width/2))*8,
748                                                                    pRef->v + (x + y*(pParam->edged_width/2))*8, pParam->edged_width/2);
749                            }
750    
751                            sad00 = pMB->sad16; //if no gmc; else sad00 = (..)
752    
753                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
754                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
755                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant;
756                            } else {
757                                    if (pMB->dquant != NO_CHANGE) {
758                                            quant += DQtab[pMB->dquant];
759                                            if (quant > 31) quant = 31;
760                                            else if (quant < 1) quant = 1;
761                                    }
762                                    pMB->quant = quant;
763                            }
764    
765  //initial skip decision  //initial skip decision
766    /* no early skip for GMC (global vector = skip vector is unknown!)  */
767                          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 */
768                                  && (SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) ) {                                  if (pMB->dquant == NO_CHANGE && sad00 < pMB->quant * INITIAL_SKIP_THRESH)
769                                  if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {                                          if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
770                                                  SkipMacroblockP(pMB, sad00);                                                  SkipMacroblockP(pMB, sad00);
771                                                  continue;                                                  continue;
772                                  }                                  }
773                          } else sad00 = 256*4096; // skip not allowed - for final skip decision                          }
774    
775                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchP(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
776                                                  y, current->motion_flags, pMB->quant,                                                  y, current->motion_flags, pMB->quant,
777                                                  &Data, pParam, pMBs, reference->mbs,                                                  &Data, pParam, pMBs, reference->mbs,
778                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
779    
780  /* 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?" */
781                          if (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)                          if (current->coding_type == P_VOP)      {
782                                  if ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH)                                  if ( (pMB->dquant == NO_CHANGE) && (sad00 < pMB->quant * MAX_SAD00_FOR_SKIP)
783                                  { SkipMacroblockP(pMB, sad00); continue; }                                  && ((100*pMB->sad16)/(sad00+1) > FINAL_SKIP_THRESH) )
784                                            if (Data.chroma || SkipDecisionP(pCurrent, pRef, x, y, pParam->edged_width, pMB->quant)) {
785                                                    SkipMacroblockP(pMB, sad00);
786                                                    continue;
787                                            }
788                            }
789    
790  /* finally, intra decision */  /* finally, intra decision */
791    
792                          InterBias = MV16_INTER_BIAS;                          InterBias = MV16_INTER_BIAS;
793                          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
794                          if (y != 0)                          if (y != 0)
795                                  if ((pMB - pParam->mb_width)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - pParam->mb_width)->mode == MODE_INTRA ) InterBias -= 80;
796                          if (x != 0)                          if (x != 0)
797                                  if ((pMB - 1)->mode == MODE_INTER ) InterBias -= 50;                                  if ((pMB - 1)->mode == MODE_INTRA ) InterBias -= 80;
798    
799                            if (Data.chroma) InterBias += 50; // to compensate bigger SAD
800    
801                          if (InterBias < pMB->sad16)  {                          if (InterBias < pMB->sad16)  {
802                                  const int32_t deviation =                                  const int32_t deviation =
# Line 613  Line 804 
804                                                    pParam->edged_width);                                                    pParam->edged_width);
805    
806                                  if (deviation < (pMB->sad16 - InterBias)) {                                  if (deviation < (pMB->sad16 - InterBias)) {
807                                          if (++iIntra >= iLimit) return 1;                                          if (++iIntra >= iLimit) { free(qimage); return 1; }
808                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
809                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
810                                                          pMB->mvs[3] = zeroMV;                                                          pMB->mvs[3] = zeroMV;
811                                            pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] =
812                                                            pMB->qmvs[3] = zeroMV;
813                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
814                                                  pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
815                                  }                                  }
816                          }                          }
817                  }                  }
818          }          }
819            free(qimage);
820    
821            if (current->coding_type == S_VOP)      /* first GMC step only for S(GMC)-VOPs */
822                    current->GMC_MV = GlobalMotionEst( pMBs, pParam, current->fcode );
823            else
824                    current->GMC_MV = zeroMV;
825    
826          return 0;          return 0;
827  }  }
828    
# Line 680  Line 880 
880  }  }
881    
882  static void  static void
883  SearchP(const uint8_t * const pRef,  SearchP(const IMAGE * const pRef,
884                  const uint8_t * const pRefH,                  const uint8_t * const pRefH,
885                  const uint8_t * const pRefV,                  const uint8_t * const pRefV,
886                  const uint8_t * const pRefHV,                  const uint8_t * const pRefHV,
# Line 702  Line 902 
902    
903          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()
904          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,
905                                  pParam->width, pParam->height, Data->iFcode);                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
906    
         Data->predMV = pmv[0];  
907          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
908          Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8;
909            Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8;
910    
911            Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16;
912          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
913          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
914          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
915            Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
916            Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
917    
918          Data->iQuant = iQuant;          Data->lambda16 = lambda_vec16[iQuant];
919            Data->lambda8 = lambda_vec8[iQuant];
920            Data->qpel_precision = 0;
921    
922          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
923                  Data->min_dx = EVEN(Data->min_dx);                  Data->min_dx = EVEN(Data->min_dx);
# Line 719  Line 925 
925                  Data->min_dy = EVEN(Data->min_dy);                  Data->min_dy = EVEN(Data->min_dy);
926                  Data->max_dy = EVEN(Data->max_dy); }                  Data->max_dy = EVEN(Data->max_dy); }
927    
928          for(i = 0;  i < 5; i++) Data->iMinSAD[i] = 256*4096;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
   
         if (inter4v) CheckCandidate = CheckCandidate16;  
         else CheckCandidate = CheckCandidate16no4v;  
929    
930          (*CheckCandidate)(Data->predMV.x, Data->predMV.y, 0, &iDirection, Data);          for(i = 0;  i < 5; i++)
931                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
932    
933          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);
934            else Data->predMV = pmv[0];
935    
936          i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);          i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);
937          Data->iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;          Data->iMinSAD[0] = pMB->sad16 + (Data->lambda16 * i * pMB->sad16)/1000;
938          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;
939          Data->iMinSAD[2] = pMB->sad8[1];          Data->iMinSAD[2] = pMB->sad8[1];
940          Data->iMinSAD[3] = pMB->sad8[2];          Data->iMinSAD[3] = pMB->sad8[2];
941          Data->iMinSAD[4] = pMB->sad8[3];          Data->iMinSAD[4] = pMB->sad8[3];
942    
         if (pMB->dquant != NO_CHANGE) inter4v = 0;  
   
943          if ((x == 0) && (y == 0)) threshA = 512;          if ((x == 0) && (y == 0)) threshA = 512;
944          else {          else {
945                  threshA = Data->temp[0] + 20;                  threshA = Data->temp[0]; // that's when we keep this SAD atm
946                  if (threshA < 512) threshA = 512;                  if (threshA < 512) threshA = 512;
947                  if (threshA > 1024) threshA = 1024; }                  if (threshA > 1024) threshA = 1024; }
948    
949          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,          PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,
950                                          prevMBs + x + y * pParam->mb_width);                                          prevMBs + x + y * pParam->mb_width);
951    
952            if (inter4v || Data->chroma) CheckCandidate = CheckCandidate16;
953            else CheckCandidate = CheckCandidate16no4v; //for extra speed
954    
955  /* main loop. checking all predictions */  /* main loop. checking all predictions */
956    
957          for (i = 1; i < 7; i++) {          for (i = 1; i < 7; i++) {
958                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
959                  CheckCandidate16(pmv[i].x, pmv[i].y, mask, &iDirection, Data);                  (*CheckCandidate)(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
960                  if (Data->iMinSAD[0] <= threshA) break;                  if (Data->iMinSAD[0] <= threshA) break;
961          }          }
962    
# Line 779  Line 985 
985                          if (!(MVequal(startMV, backupMV))) {                          if (!(MVequal(startMV, backupMV))) {
986                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
987    
988                                  CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
989                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
990                                  if (bSAD < Data->iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
991                                          Data->currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
# Line 792  Line 998 
998                          if (!(MVequal(startMV, backupMV))) {                          if (!(MVequal(startMV, backupMV))) {
999                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;                                  bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
1000    
1001                                  CheckCandidate16(startMV.x, startMV.y, 255, &iDirection, Data);                                  (*CheckCandidate)(startMV.x, startMV.y, 255, &iDirection, Data);
1002                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);                                  (*MainSearchPtr)(startMV.x, startMV.y, Data, 255);
1003                                  if (bSAD < Data->iMinSAD[0]) {                                  if (bSAD < Data->iMinSAD[0]) {
1004                                          Data->currentMV[0] = backupMV;                                          Data->currentMV[0] = backupMV;
# Line 801  Line 1007 
1007                  }                  }
1008          }          }
1009    
1010          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);          if (MotionFlags & PMV_HALFPELREFINE16) SubpelRefine(Data);
1011    
1012            for(i = 0; i < 5; i++) {
1013                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1014                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1015            }
1016    
1017            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1018    
1019                    Data->qpel_precision = 1;
1020                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1021                                    pParam->width, pParam->height, Data->iFcode, 0);
1022    
1023                    SubpelRefine(Data);
1024            }
1025    
1026            if (Data->iMinSAD[0] < (int32_t)iQuant * 30 ) inter4v = 0;
1027          if (inter4v) {          if (inter4v) {
1028                  SearchData Data8;                  SearchData Data8;
1029                  Data8.iFcode = Data->iFcode;                  Data8.iFcode = Data->iFcode;
1030                  Data8.iQuant = Data->iQuant;                  Data8.lambda8 = Data->lambda8;
1031                  Data8.iEdgedWidth = Data->iEdgedWidth;                  Data8.iEdgedWidth = Data->iEdgedWidth;
1032                    Data8.RefQ = Data->RefQ;
1033                    Data8.qpel = Data->qpel;
1034                  Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);                  Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1035                  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);
1036                  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);
1037                  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);
1038    
1039                    if (Data->chroma) {
1040                            int sumx, sumy, dx, dy;
1041    
1042                            if(pParam->m_quarterpel) {
1043                                    sumx= pMB->qmvs[0].x/2 + pMB->qmvs[1].x/2 + pMB->qmvs[2].x/2 + pMB->qmvs[3].x/2;
1044                                    sumy = pMB->qmvs[0].y/2 + pMB->qmvs[1].y/2 + pMB->qmvs[2].y/2 + pMB->qmvs[3].y/2;
1045                            } else {
1046                                    sumx = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1047                                    sumy = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1048                            }
1049                            dx = (sumx >> 3) + roundtab_76[sumx & 0xf];
1050                            dy = (sumy >> 3) + roundtab_76[sumy & 0xf];
1051    
1052                            Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);
1053                    }
1054          }          }
1055    
1056          if (!(inter4v) ||          if (!(inter4v) ||
# Line 825  Line 1064 
1064                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1065                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1066    
1067                    if(pParam->m_quarterpel) {
1068                            pMB->qmvs[0] = pMB->qmvs[1]
1069                                    = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1070                            pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predMV.x;
1071                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predMV.y;
1072                    } else {
1073                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1074                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1075                    }
1076          } else {          } else {
1077  // INTER4V MODE; all other things are already set in Search8  // INTER4V MODE; all other things are already set in Search8
1078                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1079                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1080                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1081          }          }
   
1082  }  }
1083    
1084  static void  static void
# Line 846  Line 1091 
1091                  const int block,                  const int block,
1092                  SearchData * const Data)                  SearchData * const Data)
1093  {  {
         Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);  
1094          Data->iMinSAD = OldData->iMinSAD + 1 + block;          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1095          Data->currentMV = OldData->currentMV + 1 + block;          Data->currentMV = OldData->currentMV + 1 + block;
1096            Data->currentQMV = OldData->currentQMV + 1 + block;
1097    
1098          if (block != 0)          if(pParam->m_quarterpel) {
1099                  *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *                  Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1100                    if (block != 0) *(Data->iMinSAD) += (Data->lambda8 *
1101                                                                            d_mv_bits(      Data->currentQMV->x - Data->predMV.x,
1102                                                                                                    Data->currentQMV->y - Data->predMV.y,
1103                                                                                                    Data->iFcode) * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
1104            } else {
1105                    Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1106                    if (block != 0) *(Data->iMinSAD) += (Data->lambda8 *
1107                                                                  d_mv_bits(      Data->currentMV->x - Data->predMV.x,                                                                  d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1108                                                                                          Data->currentMV->y - Data->predMV.y,                                                                                          Data->currentMV->y - Data->predMV.y,
1109                                                                                          Data->iFcode);                                                                                                  Data->iFcode) * (*Data->iMinSAD + NEIGH_8X8_BIAS))/100;
1110            }
1111    
1112          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
1113    
# Line 864  Line 1117 
1117                  Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1118    
1119                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
1120                    Data->qpel_precision = 0;
1121    
1122                  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,
1123                                  pParam->width, pParam->height, OldData->iFcode);                                  pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
   
1124                  CheckCandidate = CheckCandidate8;                  CheckCandidate = CheckCandidate8;
1125    
1126                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & PMV_EXTSEARCH8) {
1127                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1128    
1129                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1130                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1131                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1132                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1133    
1134                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);    }                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1135    
1136                            if(*(Data->iMinSAD) < temp_sad) {
1137                                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1138                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1139                            }
1140                    }
1141    
1142                    if (MotionFlags & PMV_HALFPELREFINE8) {
1143                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1144    
1145                            SubpelRefine(Data); // perform halfpel refine of current best vector
1146    
1147                            if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1148                                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1149                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1150                            }
1151                    }
1152    
1153                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(Data);                  if(pParam->m_quarterpel) {
1154                            if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1155                                    (MotionFlags & PMV_QUARTERPELREFINE8)) {
1156                            Data->qpel_precision = 1;
1157                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1158                                    pParam->width, pParam->height, OldData->iFcode, 0);
1159                            SubpelRefine(Data);
1160                            }
1161                    }
1162          }          }
1163    
1164            if(pParam->m_quarterpel) {
1165                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predMV.x;
1166                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predMV.y;
1167                    pMB->qmvs[block] = *(Data->currentQMV);
1168            }
1169            else {
1170          pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;          pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1171          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1172            }
1173    
1174          pMB->mvs[block] = *(Data->currentMV);          pMB->mvs[block] = *(Data->currentMV);
1175          pMB->sad8[block] =  4 * (*Data->iMinSAD);          pMB->sad8[block] =  4 * (*Data->iMinSAD);
   
1176  }  }
1177    
1178  /* B-frames code starts here */  /* B-frames code starts here */
# Line 947  Line 1233 
1233                          const IMAGE * const pCur,                          const IMAGE * const pCur,
1234                          const int x, const int y,                          const int x, const int y,
1235                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
                         const uint32_t iQuant,  
1236                          const uint32_t iFcode,                          const uint32_t iFcode,
1237                          const MBParam * const pParam,                          const MBParam * const pParam,
1238                          MACROBLOCK * const pMB,                          MACROBLOCK * const pMB,
1239                          const VECTOR * const predMV,                          const VECTOR * const predMV,
1240                          int32_t * const best_sad,                          int32_t * const best_sad,
1241                          const int32_t mode_current)                          const int32_t mode_current,
1242                            SearchData * const Data)
1243  {  {
1244    
1245          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1246    
1247          int i, iDirection, mask;          int i, iDirection, mask;
1248          VECTOR currentMV, pmv[7];          VECTOR pmv[7];
1249          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1250          int32_t iMinSAD = MV_MAX_ERROR;          *Data->iMinSAD = MV_MAX_ERROR;
1251          SearchData Data;          Data->iFcode = iFcode;
1252            Data->qpel_precision = 0;
1253          Data.iMinSAD = &iMinSAD;  
1254          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->Ref = pRef + (x + y * iEdgedWidth) * 16;
1255          Data.iEdgedWidth = iEdgedWidth;          Data->RefH = pRefH + (x + y * iEdgedWidth) * 16;
1256          Data.currentMV = &currentMV;          Data->RefV = pRefV + (x + y * iEdgedWidth) * 16;
1257          Data.iMinSAD = &iMinSAD;          Data->RefHV = pRefHV + (x + y * iEdgedWidth) * 16;
         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?  
1258    
1259            Data->predMV = *predMV;
1260    
1261          pmv[0] = Data.predMV;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1262          PreparePredictionsBF(pmv, x, y, pParam->mb_width,                                  pParam->width, pParam->height, iFcode, pParam->m_quarterpel);
                                         pMB, mode_current);  
1263    
1264          currentMV.x = currentMV.y = 0;          pmv[0] = Data->predMV;
1265            if (Data->qpel) { pmv[0].x /= 2; pmv[0].y /= 2; }
1266            PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
1267    
1268            Data->currentMV->x = Data->currentMV->y = 0;
1269          CheckCandidate = CheckCandidate16no4v;          CheckCandidate = CheckCandidate16no4v;
1270    
1271  // main loop. checking all predictions  // main loop. checking all predictions
1272          for (i = 0; i < 8; i++) {          for (i = 0; i < 8; i++) {
1273                  if (!(mask = make_mask(pmv, i)) ) continue;                  if (!(mask = make_mask(pmv, i)) ) continue;
1274                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, &Data);                  CheckCandidate16no4v(pmv[i].x, pmv[i].y, mask, &iDirection, Data);
1275          }          }
1276    
1277          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1008  Line 1280 
1280                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1281                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1282    
1283          (*MainSearchPtr)(currentMV.x, currentMV.y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1284    
1285            SubpelRefine(Data);
1286    
1287          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (Data->qpel) {
1288                    Data->currentQMV->x = 2*Data->currentMV->x;
1289                    Data->currentQMV->y = 2*Data->currentMV->y;
1290                    Data->qpel_precision = 1;
1291                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1292                                            pParam->width, pParam->height, iFcode, 0);
1293                    SubpelRefine(Data);
1294            }
1295    
1296  // three bits are needed to code backward mode. four for forward  // three bits are needed to code backward mode. four for forward
1297  // we treat the bits just like they were vector's  // we treat the bits just like they were vector's
1298          if (mode_current == MODE_FORWARD) iMinSAD +=  4 * lambda_vec16[iQuant];          if (mode_current == MODE_FORWARD) *Data->iMinSAD +=  4 * Data->lambda16;
1299          else iMinSAD +=  3 * lambda_vec16[iQuant];          else *Data->iMinSAD +=  3 * Data->lambda16;
   
1300    
1301          if (iMinSAD < *best_sad) {          if (*Data->iMinSAD < *best_sad) {
1302                  *best_sad = iMinSAD;                  *best_sad = *Data->iMinSAD;
1303                  pMB->mode = mode_current;                  pMB->mode = mode_current;
1304                  pMB->pmvs[0].x = currentMV.x - predMV->x;                  if (Data->qpel) {
1305                  pMB->pmvs[0].y = currentMV.y - predMV->y;                          pMB->pmvs[0].x = Data->currentQMV->x - predMV->x;
1306                  if (mode_current == MODE_FORWARD) pMB->mvs[0] = currentMV;                          pMB->pmvs[0].y = Data->currentQMV->y - predMV->y;
1307                  else pMB->b_mvs[0] = currentMV;                          if (mode_current == MODE_FORWARD)
1308                                    pMB->qmvs[0] = *Data->currentQMV;
1309                            else
1310                                    pMB->b_qmvs[0] = *Data->currentQMV;
1311                    } else {
1312                            pMB->pmvs[0].x = Data->currentMV->x - predMV->x;
1313                            pMB->pmvs[0].y = Data->currentMV->y - predMV->y;
1314                    }
1315                    if (mode_current == MODE_FORWARD)
1316                            pMB->mvs[0] = *(Data->currentMV+2) = *Data->currentMV;
1317                    else
1318                            pMB->b_mvs[0] = *(Data->currentMV+1) = *Data->currentMV; //we store currmv for interpolate search
1319    
1320          }          }
1321    
1322  }  }
# Line 1041  Line 1333 
1333                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1334                                  const int x, const int y,                                  const int x, const int y,
1335                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1336                                  const int32_t TRB, const int32_t TRD,                                  const int32_t TRB, const int32_t TRD,
1337                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1338                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1339                                  const MACROBLOCK * const b_mb,                                  const MACROBLOCK * const b_mb,
1340                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1341                                    SearchData * const Data)
1342    
1343  {  {
1344          const uint32_t iEdgedWidth = pParam->edged_width;          int32_t skip_sad;
         int32_t iMinSAD = 266*4096, skip_sad;  
1345          int k;          int k;
1346          VECTOR currentMV;  
1347          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
         SearchData Data;  
1348    
1349          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;  
1350    
1351          Data.Ref= f_Ref->y + (x + iEdgedWidth*y) * 16;          Data->Ref = f_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1352          Data.RefH = f_RefH + (x + iEdgedWidth*y) * 16;          Data->RefH = f_RefH + (x + Data->iEdgedWidth*y) * 16;
1353          Data.RefV = f_RefV + (x + iEdgedWidth*y) * 16;          Data->RefV = f_RefV + (x + Data->iEdgedWidth*y) * 16;
1354          Data.RefHV = f_RefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = f_RefHV + (x + Data->iEdgedWidth*y) * 16;
1355          Data.bRef = b_Ref->y + (x + iEdgedWidth*y) * 16;          Data->bRef = b_Ref->y + (x + Data->iEdgedWidth*y) * 16;
1356          Data.bRefH = b_RefH + (x + iEdgedWidth*y) * 16;          Data->bRefH = b_RefH + (x + Data->iEdgedWidth*y) * 16;
1357          Data.bRefV = b_RefV + (x + iEdgedWidth*y) * 16;          Data->bRefV = b_RefV + (x + Data->iEdgedWidth*y) * 16;
1358          Data.bRefHV = b_RefHV + (x + iEdgedWidth*y) * 16;          Data->bRefHV = b_RefHV + (x + Data->iEdgedWidth*y) * 16;
1359  /*  
1360  //What we do here is a complicated version of CheckCandidateDirect(0,0);          Data->max_dx = 2 * pParam->width - 2 * (x) * 16;
1361  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;
1362            Data->min_dx = -(2 * 16 + 2 * (x) * 16);
1363  */          Data->min_dy = -(2 * 16 + 2 * (y) * 16);
1364          Data.max_dx = 2 * pParam->width - 2 * (x) * 16;          if (Data->qpel) { //we measure in qpixels
1365          Data.max_dy = 2 * pParam->height - 2 * (y) * 16;                  Data->max_dx *= 2;
1366          Data.min_dx = -(2 * 16 + 2 * (x) * 16);                  Data->max_dy *= 2;
1367          Data.min_dy = -(2 * 16 + 2 * (y) * 16);                  Data->min_dx *= 2;
1368                    Data->min_dy *= 2;
1369                    Data->referencemv = b_mb->qmvs;
1370            } else Data->referencemv = b_mb->mvs;
1371            Data->qpel_precision = 0; // it's a trick. it's 1 not 0, but we need 0 here
1372    
1373          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1374                  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);
1375                  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;
1376                  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);
1377                  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;
1378    
1379                  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 )
1380                          || ( 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 )) {  
1381    
1382                          *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
1383                          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"
# Line 1100  Line 1387 
1387                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1388                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];                          pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mvs[0];
1389                          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];
1390                          Data.directmvF[1] = Data.directmvF[2] = Data.directmvF[3] = Data.directmvF[0];                          Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
1391                          Data.directmvB[1] = Data.directmvB[2] = Data.directmvB[3] = Data.directmvB[0];                          Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
1392                          break;                          break;
1393                  }                  }
1394          }          }
1395    
1396          if (b_mb->mode == MODE_INTER4V)  
1397                  CheckCandidate = CheckCandidateDirect;          if (b_mb->mode == MODE_INTER4V) CheckCandidate = CheckCandidateDirect;
1398          else CheckCandidate = CheckCandidateDirectno4v;          else CheckCandidate = CheckCandidateDirectno4v;
1399    
1400          (*CheckCandidate)(0, 0, 255, &k, &Data);          (*CheckCandidate)(0, 0, 255, &k, Data);
1401    
1402  // skip decision  // skip decision
1403          if (iMinSAD - 2 * lambda_vec16[iQuant] < (int32_t)iQuant * SKIP_THRESH_B) {          if (*Data->iMinSAD < pMB->quant * SKIP_THRESH_B) {
1404                  //checking chroma. everything copied from MC                  //possible skip - checking chroma. everything copied from MC
1405                  //this is not full chroma compensation, only it's fullpel approximation. should work though                  //this is not full chroma compensation, only it's fullpel approximation. should work though
1406                  int sum, dx, dy, b_dx, b_dy;                  int sum, dx, dy, b_dx, b_dy;
1407    
1408                    if (Data->qpel) {
1409                            sum = pMB->mvs[0].y/2 + pMB->mvs[1].y/2 + pMB->mvs[2].y/2 + pMB->mvs[3].y/2;
1410                            dy = (sum >> 3) + roundtab_76[sum & 0xf];
1411                            sum = pMB->mvs[0].x/2 + pMB->mvs[1].x/2 + pMB->mvs[2].x/2 + pMB->mvs[3].x/2;
1412                            dx = (sum >> 3) + roundtab_76[sum & 0xf];
1413    
1414                            sum = pMB->b_mvs[0].y/2 + pMB->b_mvs[1].y/2 + pMB->b_mvs[2].y/2 + pMB->b_mvs[3].y/2;
1415                            b_dy = (sum >> 3) + roundtab_76[sum & 0xf];
1416                            sum = pMB->b_mvs[0].x/2 + pMB->b_mvs[1].x/2 + pMB->b_mvs[2].x/2 + pMB->b_mvs[3].x/2;
1417                            b_dx = (sum >> 3) + roundtab_76[sum & 0xf];
1418    
1419                    } else {
1420                  sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;                  sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1421                  dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));                  dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
   
1422                  sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;                  sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1423                  dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));                  dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1424    
1425                  sum = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;                  sum = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;
1426                  b_dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));                  b_dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
   
1427                  sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;                  sum = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;
1428                  b_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));                  b_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2));
1429                    }
1430                    sum = sad8bi(pCur->u + 8*x + 8*y*(Data->iEdgedWidth/2),
1431                                            f_Ref->u + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1432                                            b_Ref->u + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1433                                            Data->iEdgedWidth/2);
1434                    sum += sad8bi(pCur->v + 8*x + 8*y*(Data->iEdgedWidth/2),
1435                                            f_Ref->v + (y*8 + dy/2) * (Data->iEdgedWidth/2) + x*8 + dx/2,
1436                                            b_Ref->v + (y*8 + b_dy/2) * (Data->iEdgedWidth/2) + x*8 + b_dx/2,
1437                                            Data->iEdgedWidth/2);
1438    
1439                  sum = sad8bi(pCur->u + 8*x + 8*y*(iEdgedWidth/2),                  if (sum < MAX_CHROMA_SAD_FOR_SKIP * pMB->quant) {
                                         f_Ref->u + (y*8 + dy/2) * (iEdgedWidth/2) + x*8 + dx/2,  
                                         b_Ref->u + (y*8 + b_dy/2) * (iEdgedWidth/2) + x*8 + b_dx/2,  
                                         iEdgedWidth/2);  
                 sum += sad8bi(pCur->v + 8*x + 8*y*(iEdgedWidth/2),  
                                         f_Ref->v + (y*8 + dy/2) * (iEdgedWidth/2) + x*8 + dx/2,  
                                         b_Ref->v + (y*8 + b_dy/2) * (iEdgedWidth/2) + x*8 + b_dx/2,  
                                         iEdgedWidth/2);  
   
                 if ((uint32_t) sum < MAX_CHROMA_SAD_FOR_SKIP * Data.iQuant) {  
1440                          pMB->mode = MODE_DIRECT_NONE_MV;                          pMB->mode = MODE_DIRECT_NONE_MV;
1441                          return iMinSAD;                          return *Data->iMinSAD;
1442                  }                  }
1443          }          }
1444    
1445          skip_sad = iMinSAD;          skip_sad = *Data->iMinSAD;
1446    
1447  //  DIRECT MODE DELTA VECTOR SEARCH.  //  DIRECT MODE DELTA VECTOR SEARCH.
1448  //      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 1451 
1451                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND16) MainSearchPtr = AdvDiamondSearch;
1452                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1453    
1454          (*MainSearchPtr)(0, 0, &Data, 255);          (*MainSearchPtr)(0, 0, Data, 255);
1455    
1456          HalfpelRefine(&Data);          SubpelRefine(Data);
1457    
1458          iMinSAD +=  1 * lambda_vec16[iQuant]; // one bit is needed to code direct mode. we treat this bit just like it was vector's          *Data->iMinSAD +=  1 * Data->lambda16; // one bit is needed to code direct mode
1459          *best_sad = iMinSAD;          *best_sad = *Data->iMinSAD;
1460    
1461          if (b_mb->mode == MODE_INTER4V)          if (b_mb->mode == MODE_INTER4V)
1462                  pMB->mode = MODE_DIRECT;                  pMB->mode = MODE_DIRECT;
1463          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation          else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation
1464    
1465          pMB->pmvs[3] = currentMV;          pMB->pmvs[3] = *Data->currentMV;
1466    
1467          for (k = 0; k < 4; k++) {          for (k = 0; k < 4; k++) {
1468                  pMB->mvs[k].x = Data.directmvF[k].x + currentMV.x;                  pMB->mvs[k].x = Data->directmvF[k].x + Data->currentMV->x;
1469                  pMB->b_mvs[k].x = ((currentMV.x == 0)                  pMB->b_mvs[k].x = (     (Data->currentMV->x == 0)
1470                                                          ? Data.directmvB[k].x                                                          ? Data->directmvB[k].x
1471                                                          : pMB->mvs[k].x - Data.referencemv[k].x);                                                          :pMB->mvs[k].x - Data->referencemv[k].x);
1472                  pMB->mvs[k].y = (Data.directmvF[k].y + currentMV.y);                  pMB->mvs[k].y = (Data->directmvF[k].y + Data->currentMV->y);
1473                  pMB->b_mvs[k].y = ((currentMV.y == 0)                  pMB->b_mvs[k].y = ((Data->currentMV->y == 0)
1474                                                          ? Data.directmvB[k].y                                                          ? Data->directmvB[k].y
1475                                                          : pMB->mvs[k].y - Data.referencemv[k].y);                                                          : pMB->mvs[k].y - Data->referencemv[k].y);
1476                    if (Data->qpel) {
1477                            pMB->qmvs[k].x = pMB->mvs[k].x; pMB->mvs[k].x /= 2;
1478                            pMB->b_qmvs[k].x = pMB->b_mvs[k].x; pMB->b_mvs[k].x /= 2;
1479                            pMB->qmvs[k].y = pMB->mvs[k].y; pMB->mvs[k].y /= 2;
1480                            pMB->b_qmvs[k].y = pMB->b_mvs[k].y; pMB->b_mvs[k].y /= 2;
1481                    }
1482    
1483                  if (b_mb->mode != MODE_INTER4V) {                  if (b_mb->mode != MODE_INTER4V) {
1484                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];                          pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
1485                          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];
1486                            pMB->qmvs[3] = pMB->qmvs[2] = pMB->qmvs[1] = pMB->qmvs[0];
1487                            pMB->b_qmvs[3] = pMB->b_qmvs[2] = pMB->b_qmvs[1] = pMB->b_qmvs[0];
1488                          break;                          break;
1489                  }                  }
1490          }          }
1491          return 0;//skip_sad;          return skip_sad;
1492  }  }
1493    
1494    
1495  static __inline void  static __inline void
1496  SearchInterpolate(const uint8_t * const f_Ref,  SearchInterpolate(const uint8_t * const f_Ref,
1497                                  const uint8_t * const f_RefH,                                  const uint8_t * const f_RefH,
# Line 1199  Line 1506 
1506                                  const uint32_t fcode,                                  const uint32_t fcode,
1507                                  const uint32_t bcode,                                  const uint32_t bcode,
1508                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
                                 const uint32_t iQuant,  
1509                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1510                                  const VECTOR * const f_predMV,                                  const VECTOR * const f_predMV,
1511                                  const VECTOR * const b_predMV,                                  const VECTOR * const b_predMV,
1512                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1513                                  int32_t * const best_sad)                                  int32_t * const best_sad,
1514                                    SearchData * const fData)
1515    
1516  {  {
 /* 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". */  
1517    
1518          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
   
1519          int iDirection, i, j;          int iDirection, i, j;
1520          int32_t iMinSAD = 256*4096;          SearchData bData;
         VECTOR currentMV[3];  
         SearchData fData, bData;  
   
         fData.iMinSAD = bData.iMinSAD = &iMinSAD;  
1521    
1522          fData.Cur = bData.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          *(bData.iMinSAD = fData->iMinSAD) = 4096*256;
1523          fData.iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;          bData.Cur = fData->Cur;
1524          fData.currentMV = currentMV; bData.currentMV = currentMV + 1;          fData->iEdgedWidth = bData.iEdgedWidth = iEdgedWidth;
1525          fData.iQuant = bData.iQuant = iQuant;          bData.currentMV = fData->currentMV + 1; bData.currentQMV = fData->currentQMV + 1;
1526          fData.iFcode = bData.bFcode = fcode; fData.bFcode = bData.iFcode = bcode;          bData.lambda16 = fData->lambda16;
1527            fData->iFcode = bData.bFcode = fcode; fData->bFcode = bData.iFcode = bcode;
1528          bData.bRef = fData.Ref = f_Ref + (x + y * iEdgedWidth) * 16;  
1529          bData.bRefH = fData.RefH = f_RefH + (x + y * iEdgedWidth) * 16;          bData.bRef = fData->Ref = f_Ref + (x + y * iEdgedWidth) * 16;
1530          bData.bRefV = fData.RefV = f_RefV + (x + y * iEdgedWidth) * 16;          bData.bRefH = fData->RefH = f_RefH + (x + y * iEdgedWidth) * 16;
1531          bData.bRefHV = fData.RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;          bData.bRefV = fData->RefV = f_RefV + (x + y * iEdgedWidth) * 16;
1532          bData.Ref = fData.bRef = b_Ref + (x + y * iEdgedWidth) * 16;          bData.bRefHV = fData->RefHV = f_RefHV + (x + y * iEdgedWidth) * 16;
1533          bData.RefH = fData.bRefH = b_RefH + (x + y * iEdgedWidth) * 16;          bData.Ref = fData->bRef = b_Ref + (x + y * iEdgedWidth) * 16;
1534          bData.RefV = fData.bRefV = b_RefV + (x + y * iEdgedWidth) * 16;          bData.RefH = fData->bRefH = b_RefH + (x + y * iEdgedWidth) * 16;
1535          bData.RefHV = fData.bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;          bData.RefV = fData->bRefV = b_RefV + (x + y * iEdgedWidth) * 16;
1536            bData.RefHV = fData->bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16;
1537          bData.bpredMV = fData.predMV = *f_predMV;          bData.RefQ = fData->RefQ;
1538          fData.bpredMV = bData.predMV = *b_predMV;          fData->qpel_precision = bData.qpel_precision = 0; bData.qpel = fData->qpel;
1539            bData.rounding = 0;
1540          currentMV[0] = pMB->mvs[0];  
1541          currentMV[1] = pMB->b_mvs[0];          bData.bpredMV = fData->predMV = *f_predMV;
1542          get_range(&fData.min_dx, &fData.max_dx, &fData.min_dy, &fData.max_dy, x, y, 16, pParam->width, pParam->height, fcode);          fData->bpredMV = bData.predMV = *b_predMV;
1543          get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode);  
1544            fData->currentMV[0] = fData->currentMV[2];
1545          if (currentMV[0].x > fData.max_dx) currentMV[0].x = fData.max_dx;          get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, pParam->m_quarterpel);
1546          if (currentMV[0].x < fData.min_dx) currentMV[0].x = fData.min_dy;          get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, pParam->m_quarterpel);
1547          if (currentMV[0].y > fData.max_dy) currentMV[0].y = fData.max_dx;  
1548          if (currentMV[0].y > fData.min_dy) currentMV[0].y = fData.min_dy;          if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1549            if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dx;
1550          if (currentMV[1].x > bData.max_dx) currentMV[1].x = bData.max_dx;          if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dy;
1551          if (currentMV[1].x < bData.min_dx) currentMV[1].x = bData.min_dy;          if (fData->currentMV[0].y < fData->min_dy) fData->currentMV[0].y = fData->min_dy;
1552          if (currentMV[1].y > bData.max_dy) currentMV[1].y = bData.max_dx;  
1553          if (currentMV[1].y > bData.min_dy) currentMV[1].y = bData.min_dy;          if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx;
1554            if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dx;
1555            if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dy;
1556            if (fData->currentMV[1].y < bData.min_dy) fData->currentMV[1].y = bData.min_dy;
1557    
1558          CheckCandidateInt(currentMV[0].x, currentMV[0].y, 255, &iDirection, &fData);          CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData);
1559    
1560  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)  //diamond. I wish we could use normal mainsearch functions (square, advdiamond)
1561    
1562          do {          do {
1563                  iDirection = 255;                  iDirection = 255;
1564                  // forward MV moves                  // forward MV moves
1565                  i = currentMV[0].x; j = currentMV[0].y;                  i = fData->currentMV[0].x; j = fData->currentMV[0].y;
1566    
1567                  CheckCandidateInt(i + 1, j, 0, &iDirection, &fData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, fData);
1568                  CheckCandidateInt(i, j + 1, 0, &iDirection, &fData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, fData);
1569                  CheckCandidateInt(i - 1, j, 0, &iDirection, &fData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, fData);
1570                  CheckCandidateInt(i, j - 1, 0, &iDirection, &fData);                  CheckCandidateInt(i, j - 1, 0, &iDirection, fData);
1571    
1572                  // backward MV moves                  // backward MV moves
1573                  i = currentMV[1].x; j = currentMV[1].y;                  i = fData->currentMV[1].x; j = fData->currentMV[1].y;
1574                  currentMV[2] = currentMV[0];                  fData->currentMV[2] = fData->currentMV[0];
   
1575                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);                  CheckCandidateInt(i + 1, j, 0, &iDirection, &bData);
1576                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);                  CheckCandidateInt(i, j + 1, 0, &iDirection, &bData);
1577                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);                  CheckCandidateInt(i - 1, j, 0, &iDirection, &bData);
# Line 1279  Line 1579 
1579    
1580          } while (!(iDirection));          } while (!(iDirection));
1581    
1582  // two bits are needed to code interpolate mode. we treat the bits just like they were vector's          *fData->iMinSAD +=  2 * fData->lambda16; // two bits are needed to code interpolate mode.
         iMinSAD +=  2 * lambda_vec16[iQuant];  
         if (iMinSAD < *best_sad) {  
                 *best_sad = iMinSAD;  
                 pMB->mvs[0] = currentMV[0];  
                 pMB->b_mvs[0] = currentMV[1];  
                 pMB->mode = MODE_INTERPOLATE;  
1583    
1584            if (fData->qpel) {
1585                    CheckCandidate = CheckCandidateInt;
1586                    fData->qpel_precision = bData.qpel_precision = 1;
1587                    get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, 0);
1588                    get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, 0);
1589                    fData->currentQMV[2].x = fData->currentQMV[0].x = 2 * fData->currentMV[0].x;
1590                    fData->currentQMV[2].y = fData->currentQMV[0].y = 2 * fData->currentMV[0].y;
1591                    fData->currentQMV[1].x = 2 * fData->currentMV[1].x;
1592                    fData->currentQMV[1].y = 2 * fData->currentMV[1].y;
1593                    SubpelRefine(fData);
1594                    fData->currentQMV[2] = fData->currentQMV[0];
1595                    SubpelRefine(&bData);
1596            }
1597    
1598            if (*fData->iMinSAD < *best_sad) {
1599                    *best_sad = *fData->iMinSAD;
1600                    pMB->mvs[0] = fData->currentMV[0];
1601                    pMB->b_mvs[0] = fData->currentMV[1];
1602                    pMB->mode = MODE_INTERPOLATE;
1603                    if (fData->qpel) {
1604                            pMB->qmvs[0] = fData->currentQMV[0];
1605                            pMB->b_qmvs[0] = fData->currentQMV[1];
1606                            pMB->pmvs[1].x = pMB->qmvs[0].x - f_predMV->x;
1607                            pMB->pmvs[1].y = pMB->qmvs[0].y - f_predMV->y;
1608                            pMB->pmvs[0].x = pMB->b_qmvs[0].x - b_predMV->x;
1609                            pMB->pmvs[0].y = pMB->b_qmvs[0].y - b_predMV->y;
1610                    } else {
1611                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;                  pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;
1612                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;                  pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;
1613                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;                  pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;
1614                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;                  pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;
1615          }          }
1616  }  }
1617    }
1618    
1619  void  void
1620  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
# Line 1306  Line 1628 
1628                                           const IMAGE * const f_refV,                                           const IMAGE * const f_refV,
1629                                           const IMAGE * const f_refHV,                                           const IMAGE * const f_refHV,
1630                                           // backward (future) reference                                           // backward (future) reference
1631                                           const MACROBLOCK * const b_mbs,                                           const FRAMEINFO * const b_reference,
1632                                           const IMAGE * const b_ref,                                           const IMAGE * const b_ref,
1633                                           const IMAGE * const b_refH,                                           const IMAGE * const b_refH,
1634                                           const IMAGE * const b_refV,                                           const IMAGE * const b_refV,
# Line 1316  Line 1638 
1638          int32_t best_sad, skip_sad;          int32_t best_sad, skip_sad;
1639          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;
1640          static const VECTOR zeroMV={0,0};          static const VECTOR zeroMV={0,0};
1641            const MACROBLOCK * const b_mbs = b_reference->mbs;
1642    
1643          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/          VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
1644    
1645          const int32_t TRB = time_pp - time_bp;          const int32_t TRB = time_pp - time_bp;
1646          const int32_t TRD = time_pp;          const int32_t TRD = time_pp;
1647            uint8_t * qimage;
1648    
1649          // note: i==horizontal, j==vertical  // some pre-inintialized data for the rest of the search
1650    
1651            SearchData Data;
1652            int32_t iMinSAD;
1653            VECTOR currentMV[3];
1654            VECTOR currentQMV[3];
1655            Data.iEdgedWidth = pParam->edged_width;
1656            Data.currentMV = currentMV; Data.currentQMV = currentQMV;
1657            Data.iMinSAD = &iMinSAD;
1658            Data.lambda16 = lambda_vec16[frame->quant];
1659            Data.qpel = pParam->m_quarterpel;
1660            Data.rounding = 0;
1661    
1662            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
1663                    return; // allocate some mem for qpel interpolated blocks
1664                                      // somehow this is dirty since I think we shouldn't use malloc outside
1665                                      // encoder_create() - so please fix me!
1666            Data.RefQ = qimage;
1667    
1668            // note: i==horizontal, j==vertical
1669          for (j = 0; j < pParam->mb_height; j++) {          for (j = 0; j < pParam->mb_height; j++) {
1670    
1671                  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 1674 
1674                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;                          MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width;
1675                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;                          const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width;
1676    
1677  /* 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 */
1678                            if (b_reference->coding_type != S_VOP)
1679                          if (b_mb->mode == MODE_NOT_CODED) {                          if (b_mb->mode == MODE_NOT_CODED) {
1680                                  pMB->mode = MODE_NOT_CODED;                                  pMB->mode = MODE_NOT_CODED;
1681                                  continue;                                  continue;
1682                          }                          }
1683    
1684                            Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16;
1685                            pMB->quant = frame->quant;
1686    
1687  /* direct search comes first, because it (1) checks for SKIP-mode  /* direct search comes first, because it (1) checks for SKIP-mode
1688          and (2) sets very good predictions for forward and backward search */          and (2) sets very good predictions for forward and backward search */
   
1689                          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,
1690                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,                                                                          b_ref, b_refH->y, b_refV->y, b_refHV->y,
1691                                                                          &frame->image,                                                                          &frame->image,
1692                                                                          i, j,                                                                          i, j,
1693                                                                          frame->motion_flags,                                                                          frame->motion_flags,
                                                                         frame->quant,  
1694                                                                          TRB, TRD,                                                                          TRB, TRD,
1695                                                                          pParam,                                                                          pParam,
1696                                                                          pMB, b_mb,                                                                          pMB, b_mb,
1697                                                                          &best_sad);                                                                          &best_sad,
1698                                                                            &Data);
1699    
1700                          if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }                          if (pMB->mode == MODE_DIRECT_NONE_MV) { n_count++; continue; }
1701    
 //                      best_sad = 256*4096; //uncomment to disable Directsearch.  
 //      To disable any other mode, just comment the function call  
   
1702                          // forward search                          // forward search
1703                          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,
1704                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1705                                                  frame->motion_flags,                                                  frame->motion_flags,
1706                                                  frame->quant, frame->fcode, pParam,                                                  frame->fcode, pParam,
1707                                                  pMB, &f_predMV, &best_sad,                                                  pMB, &f_predMV, &best_sad,
1708                                                  MODE_FORWARD);                                                  MODE_FORWARD, &Data);
1709    
1710                          // backward search                          // backward search
1711                          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,
1712                                                  &frame->image, i, j,                                                  &frame->image, i, j,
1713                                                  frame->motion_flags,                                                  frame->motion_flags,
1714                                                  frame->quant, frame->bcode, pParam,                                                  frame->bcode, pParam,
1715                                                  pMB, &b_predMV, &best_sad,                                                  pMB, &b_predMV, &best_sad,
1716                                                  MODE_BACKWARD);                                                  MODE_BACKWARD, &Data);
1717    
1718                          // 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
1719    
# Line 1381  Line 1723 
1723                                                  i, j,                                                  i, j,
1724                                                  frame->fcode, frame->bcode,                                                  frame->fcode, frame->bcode,
1725                                                  frame->motion_flags,                                                  frame->motion_flags,
1726                                                  frame->quant, pParam,                                                  pParam,
1727                                                  &f_predMV, &b_predMV,                                                  &f_predMV, &b_predMV,
1728                                                  pMB, &best_sad);                                                  pMB, &best_sad,
1729                                                    &Data);
1730    
1731                          switch (pMB->mode) {                          switch (pMB->mode) {
1732                                  case MODE_FORWARD:                                  case MODE_FORWARD:
1733                                          f_count++;                                          f_count++;
1734                                          f_predMV = pMB->mvs[0];                                          if (pParam->m_quarterpel) f_predMV = pMB->qmvs[0];
1735                                            else f_predMV = pMB->mvs[0];
1736                                          break;                                          break;
1737                                  case MODE_BACKWARD:                                  case MODE_BACKWARD:
1738                                          b_count++;                                          b_count++;
1739                                          b_predMV = pMB->b_mvs[0];                                          if (pParam->m_quarterpel) b_predMV = pMB->b_qmvs[0];
1740                                            else b_predMV = pMB->b_mvs[0];
1741                                          break;                                          break;
1742                                  case MODE_INTERPOLATE:                                  case MODE_INTERPOLATE:
1743                                          i_count++;                                          i_count++;
1744                                            if (pParam->m_quarterpel) {
1745                                                    f_predMV = pMB->qmvs[0];
1746                                                    b_predMV = pMB->b_qmvs[0];
1747                                            } else {
1748                                          f_predMV = pMB->mvs[0];                                          f_predMV = pMB->mvs[0];
1749                                          b_predMV = pMB->b_mvs[0];                                          b_predMV = pMB->b_mvs[0];
1750                                            }
1751                                          break;                                          break;
1752                                  case MODE_DIRECT:                                  case MODE_DIRECT:
1753                                  case MODE_DIRECT_NO4V:                                  case MODE_DIRECT_NO4V:
# Line 1408  Line 1758 
1758                          }                          }
1759                  }                  }
1760          }          }
1761            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);  
   
1762  }  }
1763    
1764  /* Hinted ME starts here */  /* Hinted ME starts here */
1765    
 static __inline void  
 Search8hinted(  const SearchData * const OldData,  
                                 const int x, const int y,  
                                 const uint32_t MotionFlags,  
                                 const MBParam * const pParam,  
                                 MACROBLOCK * const pMB,  
                                 const MACROBLOCK * const pMBs,  
                                 const int block)  
 {  
         SearchData Data;  
         MainSearchFunc *MainSearchPtr;  
   
         Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);  
         Data.iMinSAD = OldData->iMinSAD + 1 + block;  
         Data.currentMV = OldData->currentMV+1+block;  
         Data.iFcode = OldData->iFcode;  
         Data.iQuant = OldData->iQuant;  
   
         Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));  
         Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));  
         Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));  
         Data.RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));  
         Data.iEdgedWidth = pParam->edged_width;  
         Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));  
   
         CheckCandidate = CheckCandidate8;  
   
         if (block != 0)  
                 *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *  
                                                                 d_mv_bits(      Data.currentMV->x - Data.predMV.x,  
                                                                                         Data.currentMV->y - Data.predMV.y,  
                                                                                         Data.iFcode);  
   
   
         get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,  
                                 pParam->width, pParam->height, OldData->iFcode);  
   
         if (pMB->mode == MODE_INTER4V) {  
                 int dummy;  
                 CheckCandidate8(pMB->mvs[block].x, pMB->mvs[block].y, 0, &dummy, &Data); }  
   
         if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;  
                 else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;  
                         else MainSearchPtr = DiamondSearch;  
   
         (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);  
   
         if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);  
   
         pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;  
         pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;  
         pMB->mvs[block] = *(Data.currentMV);  
         pMB->sad8[block] =  4 * (*(Data.iMinSAD));  
 }  
   
   
1766  static void  static void
1767  SearchPhinted ( const uint8_t * const pRef,  SearchPhinted ( const IMAGE * const pRef,
1768                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
1769                                  const uint8_t * const pRefV,                                  const uint8_t * const pRefV,
1770                                  const uint8_t * const pRefHV,                                  const uint8_t * const pRefHV,
# Line 1482  Line 1773 
1773                                  const int y,                                  const int y,
1774                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1775                                  const uint32_t iQuant,                                  const uint32_t iQuant,
                                 const uint32_t iFcode,  
1776                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1777                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1778                                  int inter4v,                                  int inter4v,
1779                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
1780                                    SearchData * const Data)
1781  {  {
1782    
1783          const int32_t iEdgedWidth = pParam->edged_width;          int i, t;
   
         int i;  
         VECTOR currentMV[5];  
         int32_t iMinSAD[5];  
         int32_t temp[5];  
1784          MainSearchFunc * MainSearchPtr;          MainSearchFunc * MainSearchPtr;
         SearchData Data;  
1785    
1786          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,
1787          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
                                 pParam->width, pParam->height, iFcode);  
1788    
1789          Data.Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
1790          Data.iEdgedWidth = iEdgedWidth;          Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1791          Data.currentMV = currentMV;          Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1792          Data.iMinSAD = iMinSAD;  
1793          Data.Ref = pRef + (x + iEdgedWidth*y)*16;          Data->Ref = pRef->y + (x + Data->iEdgedWidth*y) * 16;
1794          Data.RefH = pRefH + (x + iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
1795          Data.RefV = pRefV + (x + iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
1796          Data.RefHV = pRefHV + (x + iEdgedWidth*y) * 16;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
1797          Data.temp = temp;          Data->RefCV = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8;
1798          Data.iQuant = iQuant;          Data->RefCU = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8;
1799          Data.iFcode = iFcode;          Data->qpel_precision = 0;
1800    
1801          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
1802                  Data.min_dx = EVEN(Data.min_dx);                  Data->min_dx = EVEN(Data->min_dx);
1803                  Data.max_dx = EVEN(Data.max_dx);                  Data->max_dx = EVEN(Data->max_dx);
1804                  Data.min_dy = EVEN(Data.min_dy);                  Data->min_dy = EVEN(Data->min_dy);
1805                  Data.max_dy = EVEN(Data.max_dy);                  Data->max_dy = EVEN(Data->max_dy);
1806          }          }
1807            if (pParam->m_quarterpel) Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1808            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1809    
1810          for(i = 0; i < 5; i++) iMinSAD[i] = MV_MAX_ERROR;          for(i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
1811    
1812          if (pMB->dquant != NO_CHANGE) inter4v = 0;          if (pMB->dquant != NO_CHANGE) inter4v = 0;
1813    
1814          if (inter4v)          if (inter4v || Data->chroma) CheckCandidate = CheckCandidate16;
                 CheckCandidate = CheckCandidate16;  
1815          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
1816    
   
1817          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);          pMB->mvs[0].x = EVEN(pMB->mvs[0].x);
1818          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);          pMB->mvs[0].y = EVEN(pMB->mvs[0].y);
1819          if (pMB->mvs[0].x > Data.max_dx) pMB->mvs[0].x = Data.max_dx; // this is in case iFcode changed          if (pMB->mvs[0].x > Data->max_dx) pMB->mvs[0].x = Data->max_dx; // this is in case iFcode changed
1820          if (pMB->mvs[0].x < Data.min_dx) pMB->mvs[0].x = Data.min_dx;          if (pMB->mvs[0].x < Data->min_dx) pMB->mvs[0].x = Data->min_dx;
1821          if (pMB->mvs[0].y > Data.max_dy) pMB->mvs[0].y = Data.max_dy;          if (pMB->mvs[0].y > Data->max_dy) pMB->mvs[0].y = Data->max_dy;
1822          if (pMB->mvs[0].y < Data.min_dy) pMB->mvs[0].y = Data.min_dy;          if (pMB->mvs[0].y < Data->min_dy) pMB->mvs[0].y = Data->min_dy;
1823    
1824          CheckCandidate16(pMB->mvs[0].x, pMB->mvs[0].y, 0, &i, &Data);          (*CheckCandidate)(pMB->mvs[0].x, pMB->mvs[0].y, 0, &t, Data);
1825    
1826          if (pMB->mode == MODE_INTER4V)          if (pMB->mode == MODE_INTER4V)
1827                  for (i = 1; i < 4; i++) { // all four vectors will be used as four predictions for 16x16 search                  for (i = 1; i < 4; i++) { // all four vectors will be used as four predictions for 16x16 search
1828                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);                          pMB->mvs[i].x = EVEN(pMB->mvs[i].x);
1829                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);                          pMB->mvs[i].y = EVEN(pMB->mvs[i].y);
1830                          if (!(make_mask(pMB->mvs, i)))                          if (!(make_mask(pMB->mvs, i)))
1831                                  CheckCandidate16(pMB->mvs[i].x, pMB->mvs[i].y, 0, &i, &Data);                                  (*CheckCandidate)(pMB->mvs[i].x, pMB->mvs[i].y, 0, &t, Data);
1832                  }                  }
1833    
1834          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
# Line 1553  Line 1837 
1837                  MainSearchPtr = AdvDiamondSearch;                  MainSearchPtr = AdvDiamondSearch;
1838                  else MainSearchPtr = DiamondSearch;                  else MainSearchPtr = DiamondSearch;
1839    
1840          (*MainSearchPtr)(currentMV->x, currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1841    
1842          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(&Data);          if (MotionFlags & PMV_HALFPELREFINE16) SubpelRefine(Data);
1843    
1844          if (inter4v)          for(i = 0; i < 5; i++) {
1845                  for(i = 0; i < 4; i++)                  Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1846                          Search8hinted(&Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                  Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1847            }
1848    
1849            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1850                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1851                                    pParam->width, pParam->height, Data->iFcode, 0);
1852                    Data->qpel_precision = 1;
1853                    SubpelRefine(Data);
1854            }
1855    
1856            if (inter4v) {
1857                    SearchData Data8;
1858                    Data8.iFcode = Data->iFcode;
1859                    Data8.lambda8 = Data->lambda8;
1860                    Data8.iEdgedWidth = Data->iEdgedWidth;
1861                    Data8.RefQ = Data->RefQ;
1862                    Data8.qpel = Data->qpel;
1863                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1864                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1865                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1866                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1867    
1868                    if (Data->chroma) {
1869                            int sumx, sumy, dx, dy;
1870    
1871                            if(pParam->m_quarterpel) {
1872                                    sumx= pMB->qmvs[0].x/2 + pMB->qmvs[1].x/2 + pMB->qmvs[2].x/2 + pMB->qmvs[3].x/2;
1873                                    sumy = pMB->qmvs[0].y/2 + pMB->qmvs[1].y/2 + pMB->qmvs[2].y/2 + pMB->qmvs[3].y/2;
1874                            } else {
1875                                    sumx = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
1876                                    sumy = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
1877                            }
1878                            dx = (sumx >> 3) + roundtab_76[sumx & 0xf];
1879                            dy = (sumy >> 3) + roundtab_76[sumy & 0xf];
1880    
1881                            Data->iMinSAD[1] += ChromaSAD(dx, dy, Data);
1882                    }
1883            }
1884    
1885          if (!(inter4v) ||          if (!(inter4v) ||
1886                  (iMinSAD[0] < iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3] +
1887                                                            Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant )) {
1888  // INTER MODE  // INTER MODE
   
1889                  pMB->mode = MODE_INTER;                  pMB->mode = MODE_INTER;
1890                  pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1891                          = pMB->mvs[2] = pMB->mvs[3] = currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1892    
1893                    pMB->qmvs[0] = pMB->qmvs[1]
1894                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1895    
1896                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1897                          pMB->sad8[2] = pMB->sad8[3] =  iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1898    
1899                  pMB->pmvs[0].x = currentMV[0].x - Data.predMV.x;                  if(pParam->m_quarterpel) {
1900                  pMB->pmvs[0].y = currentMV[0].y - Data.predMV.y;                          pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predMV.x;
1901                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predMV.y;
1902          } else {          } else {
1903  // INTER4V MODE; all other things are already set in Search8hinted                          pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1904                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1905                    }
1906            } else {
1907    // INTER4V MODE; all other things are already set in Search8
1908                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1909                  pMB->sad16 = iMinSAD[1] + iMinSAD[2] + iMinSAD[3] + iMinSAD[4] + IMV16X16 * iQuant;                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3]
1910                                                    + Data->iMinSAD[4] + IMV16X16 * iQuant;
1911          }          }
1912    
1913  }  }
# Line 1595  Line 1925 
1925          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
1926    
1927          uint32_t x, y;          uint32_t x, y;
1928            uint8_t * qimage;
1929            int32_t temp[5], quant = current->quant;
1930            int32_t iMinSAD[5];
1931            VECTOR currentMV[5], currentQMV[5];
1932            SearchData Data;
1933            Data.iEdgedWidth = pParam->edged_width;
1934            Data.currentMV = currentMV;
1935            Data.currentQMV = currentQMV;
1936            Data.iMinSAD = iMinSAD;
1937            Data.temp = temp;
1938            Data.iFcode = current->fcode;
1939            Data.rounding = pParam->m_rounding_type;
1940            Data.qpel = pParam->m_quarterpel;
1941            Data.chroma = current->global_flags & XVID_ME_COLOUR;
1942    
1943            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
1944                    return; // allocate some mem for qpel interpolated blocks
1945                                      // somehow this is dirty since I think we shouldn't use malloc outside
1946                                      // encoder_create() - so please fix me!
1947    
1948            Data.RefQ = qimage;
1949    
1950          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
1951    
# Line 1609  Line 1960 
1960                          if (!(current->global_flags & XVID_LUMIMASKING)) {                          if (!(current->global_flags & XVID_LUMIMASKING)) {
1961                                  pMB->dquant = NO_CHANGE;                                  pMB->dquant = NO_CHANGE;
1962                                  pMB->quant = current->quant; }                                  pMB->quant = current->quant; }
1963                            else {
1964                                    if (pMB->dquant != NO_CHANGE) {
1965                                            quant += DQtab[pMB->dquant];
1966                                            if (quant > 31) quant = 31;
1967                                            else if (quant < 1) quant = 1;
1968                                    }
1969                                    pMB->quant = quant;
1970                            }
1971    
1972                          SearchPhinted(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchPhinted(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
1973                                                          y, current->motion_flags, pMB->quant,                                                          y, current->motion_flags, pMB->quant,
1974                                                          current->fcode, pParam, pMBs,                                                          pParam, pMBs, current->global_flags & XVID_INTER4V, pMB,
1975                                                          current->global_flags & XVID_INTER4V, pMB);                                                          &Data);
1976    
1977                  }                  }
1978          }          }
1979            free(qimage);
1980  }  }
1981    
1982  static __inline int  static __inline int
# Line 1624  Line 1984 
1984                                  const uint8_t * const pCur,                                  const uint8_t * const pCur,
1985                                  const int x,                                  const int x,
1986                                  const int y,                                  const int y,
                                 const uint32_t iFcode,  
1987                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1988                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1989                                  MACROBLOCK * const pMB)                                  MACROBLOCK * const pMB,
1990                                    SearchData * const Data)
1991  {  {
1992    
1993          const int32_t iEdgedWidth = pParam->edged_width;          int i = 255, mask;
1994          int i, mask;          VECTOR pmv[3];
1995          VECTOR currentMV, pmv[3];          *(Data->iMinSAD) = MV_MAX_ERROR;
1996          int32_t iMinSAD = MV_MAX_ERROR;  
1997          SearchData Data;          //median is only used as prediction. it doesn't have to be real
1998            if (x == 1 && y == 1) Data->predMV.x = Data->predMV.y = 0;
1999          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          else
2000          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 16,                  if (x == 1) //left macroblock does not have any vector now
2001                                  pParam->width, pParam->height, iFcode);                          Data->predMV = (pMB - pParam->mb_width)->mvs[0]; // top instead of median
2002                    else if (y == 1) // top macroblock don't have it's vector
2003                            Data->predMV = (pMB - 1)->mvs[0]; // left instead of median
2004                            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); //else median
2005    
2006          Data.Cur = pCur + (x + y * iEdgedWidth) * 16;          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2007          Data.iEdgedWidth = iEdgedWidth;                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
         Data.currentMV = &currentMV;  
         Data.iMinSAD = &iMinSAD;  
         Data.Ref = pRef + (x + iEdgedWidth*y)*16;  
         Data.iQuant = 2;  
         Data.iFcode = iFcode;  
2008    
2009          CheckCandidate = CheckCandidate16no4vI;          Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
2010            Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
2011    
2012          pmv[1].x = EVEN(pMB->mvs[0].x);          pmv[1].x = EVEN(pMB->mvs[0].x);
2013          pmv[1].y = EVEN(pMB->mvs[0].y);          pmv[1].y = EVEN(pMB->mvs[0].y);
2014          pmv[0].x = EVEN(Data.predMV.x);          pmv[2].x = EVEN(Data->predMV.x);
2015          pmv[0].y = EVEN(Data.predMV.y);          pmv[2].y = EVEN(Data->predMV.y);
2016          pmv[2].x = pmv[2].y = 0;          pmv[0].x = pmv[0].y = 0;
2017    
2018            (*CheckCandidate)(0, 0, 255, &i, Data);
2019    
2020    //early skip for 0,0
2021            if (*Data->iMinSAD < MAX_SAD00_FOR_SKIP * 4) {
2022                    pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
2023                    pMB->mode = MODE_NOT_CODED;
2024                    return 0;
2025            }
2026    
         CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, &Data);  
2027          if (!(mask = make_mask(pmv, 1)))          if (!(mask = make_mask(pmv, 1)))
2028                  CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, &Data);                  (*CheckCandidate)(pmv[1].x, pmv[1].y, mask, &i, Data);
2029          if (!(mask = make_mask(pmv, 2)))          if (!(mask = make_mask(pmv, 2)))
2030                  CheckCandidate16no4vI(0, 0, mask, &i, &Data);                  (*CheckCandidate)(pmv[2].x, pmv[2].y, mask, &i, Data);
   
         DiamondSearch(currentMV.x, currentMV.y, &Data, i);  
2031    
2032          pMB->mvs[0] = pMB->mvs[1]          if (*Data->iMinSAD > MAX_SAD00_FOR_SKIP * 4) // diamond only if needed
2033                          = pMB->mvs[2] = pMB->mvs[3] = currentMV; // all, for future get_pmv()                  DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i);
2034    
2035          return iMinSAD;          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
2036            pMB->mode = MODE_INTER;
2037            return *(Data->iMinSAD);
2038  }  }
2039    
2040  #define INTRA_THRESH    1350  #define INTRA_THRESH    1350
2041  #define INTER_THRESH    900  #define INTER_THRESH    1200
2042    
2043    
2044  int  int
2045  MEanalysis(     const IMAGE * const pRef,  MEanalysis(     const IMAGE * const pRef,
2046                          const IMAGE * const pCurrent,                          FRAMEINFO * const Current,
2047                          MBParam * const pParam,                          MBParam * const pParam,
2048                          MACROBLOCK * const pMBs,                          int maxIntra, //maximum number if non-I frames
2049                          const uint32_t iFcode)                          int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame
2050                            int bCount) // number if B frames in a row
2051  {  {
2052          uint32_t x, y, intra = 0;          uint32_t x, y, intra = 0;
2053          int sSAD = 0;          int sSAD = 0;
2054            MACROBLOCK * const pMBs = Current->mbs;
2055            const IMAGE * const pCurrent = &Current->image;
2056            int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH;
2057    
2058            VECTOR currentMV;
2059            int32_t iMinSAD;
2060            SearchData Data;
2061            Data.iEdgedWidth = pParam->edged_width;
2062            Data.currentMV = &currentMV;
2063            Data.iMinSAD = &iMinSAD;
2064            Data.iFcode = Current->fcode;
2065            CheckCandidate = CheckCandidate16no4vI;
2066    
2067            if (intraCount < 10) // we're right after an I frame
2068                    IntraThresh += 4 * (intraCount - 10) * (intraCount - 10);
2069            else
2070                    if ( 5*(maxIntra - intraCount) < maxIntra) // we're close to maximum. 2 sec when max is 10 sec
2071                            IntraThresh -= (IntraThresh * (maxIntra - 5*(maxIntra - intraCount)))/maxIntra;
2072    
2073    
2074            InterThresh += 400 * (1 - bCount);
2075            if (InterThresh < 200) InterThresh = 200;
2076    
2077          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
2078    
2079          for (y = 0; y < pParam->mb_height-1; y++) {          for (y = 1; y < pParam->mb_height-1; y++) {
2080                  for (x = 0; x < pParam->mb_width; x++) {                  for (x = 1; x < pParam->mb_width-1; x++) {
2081                          int sad, dev;                          int sad, dev;
   
2082                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];                          MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
2083    
2084                          sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,                          sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y,
2085                                                                  iFcode, pParam, pMBs, pMB);                                                                  pParam, pMBs, pMB, &Data);
2086    
2087                          if ( x != 0 && y != 0 && x != pParam->mb_width-1 ) { //no edge macroblocks, they just don't work                          if (sad > IntraThresh) {
                                 if (sad > INTRA_THRESH) {  
2088                                          dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,                                          dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16,
2089                                                                    pParam->edged_width);                                                                    pParam->edged_width);
2090                                          if (dev + INTRA_THRESH < sad) intra++;                                  if (dev + IntraThresh < sad) {
2091                                          if (intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame                                          pMB->mode = MODE_INTRA;
2092                                            if (++intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2;  // I frame
2093                                  }                                  }
                                 sSAD += sad;  
2094                          }                          }
2095                            sSAD += sad;
2096                  }                  }
2097          }          }
2098          sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);          sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2);
2099          if (sSAD > INTER_THRESH ) return 1; //P frame          if (sSAD > InterThresh ) return 1; //P frame
2100          emms();          emms();
2101          return 0; // B frame          return 0; // B frame
2102    
2103  }  }
2104    
2105    int
2106    FindFcode(      const MBParam * const pParam,
2107                            const FRAMEINFO * const current)
2108    {
2109            uint32_t x, y;
2110            int max = 0, min = 0, i;
2111    
2112            for (y = 0; y < pParam->mb_height; y++) {
2113                    for (x = 0; x < pParam->mb_width; x++) {
2114    
2115                            MACROBLOCK *pMB = &current->mbs[x + y * pParam->mb_width];
2116                            for(i = 0; i < (pMB->mode == MODE_INTER4V ? 4:1); i++) {
2117                                    if (pMB->mvs[i].x > max) max = pMB->mvs[i].x;
2118                                    if (pMB->mvs[i].y > max) max = pMB->mvs[i].y;
2119    
2120                                    if (pMB->mvs[i].x < min) min = pMB->mvs[i].x;
2121                                    if (pMB->mvs[i].y < min) min = pMB->mvs[i].y;
2122                            }
2123                    }
2124            }
2125    
2126            min = -min;
2127            max += 1;
2128            if (min > max) max = min;
2129            if (pParam->m_quarterpel) max *= 2;
2130    
2131            for (i = 1; (max > 32 << (i - 1)); i++);
2132            return i;
2133    }
2134    
2135    static void
2136    CheckGMC(int x, int y, const int dir, int * iDirection,
2137                    const MACROBLOCK * const pMBs, uint32_t * bestcount, VECTOR * GMC,
2138                    const MBParam * const pParam)
2139    {
2140            uint32_t mx, my, a, count = 0;
2141    
2142            for (my = 1; my < pParam->mb_height-1; my++)
2143                    for (mx = 1; mx < pParam->mb_width-1; mx++) {
2144                            VECTOR mv;
2145                            const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2146                            if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED) continue;
2147                            mv = pMB->mvs[0];
2148                            a = ABS(mv.x - x) + ABS(mv.y - y);
2149                            if (a < 6) count += 6 - a;
2150                    }
2151    
2152            if (count > *bestcount) {
2153                    *bestcount = count;
2154                    *iDirection = dir;
2155                    GMC->x = x; GMC->y = y;
2156            }
2157    }
2158    
2159    
2160    static VECTOR
2161    GlobalMotionEst(const MACROBLOCK * const pMBs, const MBParam * const pParam, const uint32_t iFcode)
2162    {
2163    
2164            uint32_t count, bestcount = 0;
2165            int x, y;
2166            VECTOR gmc = {0,0};
2167            int step, min_x, max_x, min_y, max_y;
2168            uint32_t mx, my;
2169            int iDirection, bDirection;
2170    
2171            min_x = min_y = -32<<iFcode;
2172            max_x = max_y = 32<<iFcode;
2173    
2174    //step1: let's find a rough camera panning
2175            for (step = 32; step >= 2; step /= 2) {
2176                    bestcount = 0;
2177                    for (y = min_y; y <= max_y; y += step)
2178                            for (x = min_x ; x <= max_x; x += step) {
2179                                    count = 0;
2180                                    //for all macroblocks
2181                                    for (my = 1; my < pParam->mb_height-1; my++)
2182                                            for (mx = 1; mx < pParam->mb_width-1; mx++) {
2183                                                    const MACROBLOCK *pMB = &pMBs[mx + my * pParam->mb_width];
2184                                                    VECTOR mv;
2185    
2186                                                    if (pMB->mode == MODE_INTRA || pMB->mode == MODE_NOT_CODED)
2187                                                            continue;
2188    
2189                                                    mv = pMB->mvs[0];
2190                                                    if ( ABS(mv.x - x) <= step && ABS(mv.y - y) <= step )   /* GMC translation is always halfpel-res */
2191                                                            count++;
2192                                            }
2193                                    if (count >= bestcount) { bestcount = count; gmc.x = x; gmc.y = y; }
2194                            }
2195                    min_x = gmc.x - step;
2196                    max_x = gmc.x + step;
2197                    min_y = gmc.y - step;
2198                    max_y = gmc.y + step;
2199    
2200            }
2201    
2202            if (bestcount < (pParam->mb_height-2)*(pParam->mb_width-2)/10)
2203                    gmc.x = gmc.y = 0; //no camara pan, no GMC
2204    
2205    // step2: let's refine camera panning using gradiend-descent approach.
2206    // TODO: more warping points may be evaluated here (like in interpolate mode search - two vectors in one diamond)
2207            bestcount = 0;
2208            CheckGMC(gmc.x, gmc.y, 255, &iDirection, pMBs, &bestcount, &gmc, pParam);
2209            do {
2210                    x = gmc.x; y = gmc.y;
2211                    bDirection = iDirection; iDirection = 0;
2212                    if (bDirection & 1) CheckGMC(x - 1, y, 1+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2213                    if (bDirection & 2) CheckGMC(x + 1, y, 2+4+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2214                    if (bDirection & 4) CheckGMC(x, y - 1, 1+2+4, &iDirection, pMBs, &bestcount, &gmc, pParam);
2215                    if (bDirection & 8) CheckGMC(x, y + 1, 1+2+8, &iDirection, pMBs, &bestcount, &gmc, pParam);
2216    
2217            } while (iDirection);
2218    
2219            if (pParam->m_quarterpel) {
2220                    gmc.x *= 2;
2221                    gmc.y *= 2;     /* we store the halfpel value as pseudo-qpel to make comparison easier */
2222            }
2223    
2224            return gmc;
2225    }

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

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