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

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

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