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

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

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