]> rtime.felk.cvut.cz Git - frescor/ffmpeg.git/blob - libavcodec/motion_est_template.c
motion estimation cleanup
[frescor/ffmpeg.git] / libavcodec / motion_est_template.c
1 /*
2  * Motion estimation 
3  * Copyright (c) 2002-2004 Michael Niedermayer
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  */
20  
21 /**
22  * @file motion_est_template.c
23  * Motion estimation template.
24  */
25
26 //lets hope gcc will remove the unused vars ...(gcc 3.2.2 seems to do it ...)
27 #define LOAD_COMMON\
28     uint32_t * const score_map= s->me.score_map;\
29     const int xmin= s->me.xmin;\
30     const int ymin= s->me.ymin;\
31     const int xmax= s->me.xmax;\
32     const int ymax= s->me.ymax;\
33     uint8_t *mv_penalty= s->me.current_mv_penalty;\
34     const int pred_x= s->me.pred_x;\
35     const int pred_y= s->me.pred_y;\
36
37 #define CHECK_HALF_MV(dx, dy, x, y)\
38 {\
39     const int hx= 2*(x)+(dx);\
40     const int hy= 2*(y)+(dy);\
41     d= cmp(s, x, y, dx, dy, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);\
42     d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\
43     COPY3_IF_LT(dmin, d, bx, hx, by, hy)\
44 }
45
46 #if 0
47 static int hpel_motion_search)(MpegEncContext * s,
48                                   int *mx_ptr, int *my_ptr, int dmin,
49                                   uint8_t *ref_data[3], 
50                                   int size)
51 {
52     const int xx = 16 * s->mb_x + 8*(n&1);
53     const int yy = 16 * s->mb_y + 8*(n>>1);
54     const int mx = *mx_ptr;
55     const int my = *my_ptr;
56     const int penalty_factor= s->me.sub_penalty_factor;
57     
58     LOAD_COMMON
59     
60  //   INIT;
61  //FIXME factorize
62     me_cmp_func cmp, chroma_cmp, cmp_sub, chroma_cmp_sub;
63
64     if(s->no_rounding /*FIXME b_type*/){
65         hpel_put= &s->dsp.put_no_rnd_pixels_tab[size];
66         chroma_hpel_put= &s->dsp.put_no_rnd_pixels_tab[size+1];
67     }else{
68         hpel_put=& s->dsp.put_pixels_tab[size];
69         chroma_hpel_put= &s->dsp.put_pixels_tab[size+1];
70     }
71     cmpf= s->dsp.me_cmp[size];
72     chroma_cmpf= s->dsp.me_cmp[size+1];
73     cmp_sub= s->dsp.me_sub_cmp[size];
74     chroma_cmp_sub= s->dsp.me_sub_cmp[size+1];
75
76     if(s->me.skip){ //FIXME somehow move up (benchmark)
77         *mx_ptr = 0;
78         *my_ptr = 0;
79         return dmin;
80     }
81         
82     if(s->avctx->me_cmp != s->avctx->me_sub_cmp){
83         CMP_HPEL(dmin, 0, 0, mx, my, size);
84         if(mx || my)
85             dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor;
86     }
87         
88     if (mx > xmin && mx < xmax && 
89         my > ymin && my < ymax) {
90         int bx=2*mx, by=2*my;
91         int d= dmin;
92         
93         CHECK_HALF_MV(1, 1, mx-1, my-1)
94         CHECK_HALF_MV(0, 1, mx  , my-1)        
95         CHECK_HALF_MV(1, 1, mx  , my-1)
96         CHECK_HALF_MV(1, 0, mx-1, my  )
97         CHECK_HALF_MV(1, 0, mx  , my  )
98         CHECK_HALF_MV(1, 1, mx-1, my  )
99         CHECK_HALF_MV(0, 1, mx  , my  )        
100         CHECK_HALF_MV(1, 1, mx  , my  )
101
102         assert(bx >= xmin*2 || bx <= xmax*2 || by >= ymin*2 || by <= ymax*2);
103
104         *mx_ptr = bx;
105         *my_ptr = by;
106     }else{
107         *mx_ptr =2*mx;
108         *my_ptr =2*my;
109     }
110
111     return dmin;
112 }
113
114 #else
115 static int hpel_motion_search(MpegEncContext * s,
116                                   int *mx_ptr, int *my_ptr, int dmin,
117                                   int src_index, int ref_index,
118                                   int size, int h)
119 {
120     const int mx = *mx_ptr;
121     const int my = *my_ptr;   
122     const int penalty_factor= s->me.sub_penalty_factor;
123     me_cmp_func cmp_sub, chroma_cmp_sub;
124     int bx=2*mx, by=2*my;
125
126     LOAD_COMMON
127     int flags= s->me.sub_flags;
128     
129  //FIXME factorize
130
131     cmp_sub= s->dsp.me_sub_cmp[size];
132     chroma_cmp_sub= s->dsp.me_sub_cmp[size+1];
133
134     if(s->me.skip){ //FIXME move out of hpel?
135         *mx_ptr = 0;
136         *my_ptr = 0;
137         return dmin;
138     }
139         
140     if(s->avctx->me_cmp != s->avctx->me_sub_cmp){
141         dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
142         if(mx || my || size>0)
143             dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor;
144     }
145         
146     if (mx > xmin && mx < xmax && 
147         my > ymin && my < ymax) {
148         int d= dmin;
149         const int index= (my<<ME_MAP_SHIFT) + mx;
150         const int t= score_map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] 
151                      + (mv_penalty[bx   - pred_x] + mv_penalty[by-2 - pred_y])*s->me.penalty_factor;
152         const int l= score_map[(index- 1               )&(ME_MAP_SIZE-1)]
153                      + (mv_penalty[bx-2 - pred_x] + mv_penalty[by   - pred_y])*s->me.penalty_factor;
154         const int r= score_map[(index+ 1               )&(ME_MAP_SIZE-1)]
155                      + (mv_penalty[bx+2 - pred_x] + mv_penalty[by   - pred_y])*s->me.penalty_factor;
156         const int b= score_map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)]
157                      + (mv_penalty[bx   - pred_x] + mv_penalty[by+2 - pred_y])*s->me.penalty_factor;
158     
159 #if 1
160         int key;
161         int map_generation= s->me.map_generation;
162 #ifndef NDEBUG
163         uint32_t *map= s->me.map;
164 #endif
165         key= ((my-1)<<ME_MAP_MV_BITS) + (mx) + map_generation;
166         assert(map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key);
167         key= ((my+1)<<ME_MAP_MV_BITS) + (mx) + map_generation;
168         assert(map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key);
169         key= ((my)<<ME_MAP_MV_BITS) + (mx+1) + map_generation;
170         assert(map[(index+1)&(ME_MAP_SIZE-1)] == key);
171         key= ((my)<<ME_MAP_MV_BITS) + (mx-1) + map_generation;
172         assert(map[(index-1)&(ME_MAP_SIZE-1)] == key);
173 #endif                
174         if(t<=b){
175             CHECK_HALF_MV(0, 1, mx  ,my-1)
176             if(l<=r){
177                 CHECK_HALF_MV(1, 1, mx-1, my-1)
178                 if(t+r<=b+l){
179                     CHECK_HALF_MV(1, 1, mx  , my-1)
180                 }else{
181                     CHECK_HALF_MV(1, 1, mx-1, my  )
182                 }
183                 CHECK_HALF_MV(1, 0, mx-1, my  )
184             }else{
185                 CHECK_HALF_MV(1, 1, mx  , my-1)
186                 if(t+l<=b+r){
187                     CHECK_HALF_MV(1, 1, mx-1, my-1)
188                 }else{
189                     CHECK_HALF_MV(1, 1, mx  , my  )
190                 }
191                 CHECK_HALF_MV(1, 0, mx  , my  )
192             }
193         }else{
194             if(l<=r){
195                 if(t+l<=b+r){
196                     CHECK_HALF_MV(1, 1, mx-1, my-1)
197                 }else{
198                     CHECK_HALF_MV(1, 1, mx  , my  )
199                 }
200                 CHECK_HALF_MV(1, 0, mx-1, my)
201                 CHECK_HALF_MV(1, 1, mx-1, my)
202             }else{
203                 if(t+r<=b+l){
204                     CHECK_HALF_MV(1, 1, mx  , my-1)
205                 }else{
206                     CHECK_HALF_MV(1, 1, mx-1, my)
207                 }
208                 CHECK_HALF_MV(1, 0, mx  , my)
209                 CHECK_HALF_MV(1, 1, mx  , my)
210             }
211             CHECK_HALF_MV(0, 1, mx  , my)
212         }
213         assert(bx >= xmin*2 && bx <= xmax*2 && by >= ymin*2 && by <= ymax*2);
214     }
215
216     *mx_ptr = bx;
217     *my_ptr = by;
218     
219     return dmin;
220 }
221 #endif
222
223 static int inline get_mb_score(MpegEncContext * s, int mx, int my, int src_index,
224                                int ref_index)
225 {
226 //    const int check_luma= s->dsp.me_sub_cmp != s->dsp.mb_cmp;
227     const int size= 0;
228     const int h= 16;
229     const int penalty_factor= s->me.mb_penalty_factor;
230     const int flags= s->me.mb_flags;
231     const int qpel= flags & FLAG_QPEL;
232     const int mask= 1+2*qpel;
233     me_cmp_func cmp_sub, chroma_cmp_sub;
234     int d;
235
236     LOAD_COMMON
237     
238  //FIXME factorize
239
240     cmp_sub= s->dsp.mb_cmp[size];
241     chroma_cmp_sub= s->dsp.mb_cmp[size+1];
242     
243     assert(!s->me.skip);
244     assert(s->avctx->me_sub_cmp != s->avctx->mb_cmp);
245
246     d= cmp(s, mx>>(qpel+1), my>>(qpel+1), mx&mask, my&mask, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
247     //FIXME check cbp before adding penalty for (0,0) vector
248     if(mx || my || size>0)
249         d += (mv_penalty[mx - pred_x] + mv_penalty[my - pred_y])*penalty_factor;
250         
251     return d;
252 }
253
254 #define CHECK_QUARTER_MV(dx, dy, x, y)\
255 {\
256     const int hx= 4*(x)+(dx);\
257     const int hy= 4*(y)+(dy);\
258     d= cmp(s, x, y, dx, dy, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
259     d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\
260     COPY3_IF_LT(dmin, d, bx, hx, by, hy)\
261 }
262
263 static int qpel_motion_search(MpegEncContext * s,
264                                   int *mx_ptr, int *my_ptr, int dmin,
265                                   int src_index, int ref_index,                                  
266                                   int size, int h)
267 {
268     const int mx = *mx_ptr;
269     const int my = *my_ptr;   
270     const int penalty_factor= s->me.sub_penalty_factor;
271     const int map_generation= s->me.map_generation;
272     const int subpel_quality= s->avctx->me_subpel_quality;
273     uint32_t *map= s->me.map;
274     me_cmp_func cmpf, chroma_cmpf;
275     me_cmp_func cmp_sub, chroma_cmp_sub;
276
277     LOAD_COMMON
278     int flags= s->me.sub_flags;
279     
280     cmpf= s->dsp.me_cmp[size];
281     chroma_cmpf= s->dsp.me_cmp[size+1]; //factorize FIXME
282  //FIXME factorize
283
284     cmp_sub= s->dsp.me_sub_cmp[size];
285     chroma_cmp_sub= s->dsp.me_sub_cmp[size+1];
286
287     if(s->me.skip){ //FIXME somehow move up (benchmark)
288         *mx_ptr = 0;
289         *my_ptr = 0;
290         return dmin;
291     }
292         
293     if(s->avctx->me_cmp != s->avctx->me_sub_cmp){
294         dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
295         if(mx || my || size>0)
296             dmin += (mv_penalty[4*mx - pred_x] + mv_penalty[4*my - pred_y])*penalty_factor;
297     }
298         
299     if (mx > xmin && mx < xmax && 
300         my > ymin && my < ymax) {
301         int bx=4*mx, by=4*my;
302         int d= dmin;
303         int i, nx, ny;
304         const int index= (my<<ME_MAP_SHIFT) + mx;
305         const int t= score_map[(index-(1<<ME_MAP_SHIFT)  )&(ME_MAP_SIZE-1)];
306         const int l= score_map[(index- 1                 )&(ME_MAP_SIZE-1)];
307         const int r= score_map[(index+ 1                 )&(ME_MAP_SIZE-1)];
308         const int b= score_map[(index+(1<<ME_MAP_SHIFT)  )&(ME_MAP_SIZE-1)];
309         const int c= score_map[(index                    )&(ME_MAP_SIZE-1)];
310         int best[8];
311         int best_pos[8][2];
312         
313         memset(best, 64, sizeof(int)*8);
314 #if 1
315         if(s->me.dia_size>=2){        
316             const int tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
317             const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
318             const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
319             const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
320
321             for(ny= -3; ny <= 3; ny++){
322                 for(nx= -3; nx <= 3; nx++){
323                     const int t2= nx*nx*(tr + tl - 2*t) + 4*nx*(tr-tl) + 32*t;
324                     const int c2= nx*nx*( r +  l - 2*c) + 4*nx*( r- l) + 32*c;
325                     const int b2= nx*nx*(br + bl - 2*b) + 4*nx*(br-bl) + 32*b;
326                     int score= ny*ny*(b2 + t2 - 2*c2) + 4*ny*(b2 - t2) + 32*c2;
327                     int i;
328                     
329                     if((nx&3)==0 && (ny&3)==0) continue;
330                     
331                     score += 1024*(mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;
332                     
333 //                    if(nx&1) score-=1024*s->me.penalty_factor;
334 //                    if(ny&1) score-=1024*s->me.penalty_factor;
335                     
336                     for(i=0; i<8; i++){
337                         if(score < best[i]){
338                             memmove(&best[i+1], &best[i], sizeof(int)*(7-i));
339                             memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i));
340                             best[i]= score;
341                             best_pos[i][0]= nx + 4*mx;
342                             best_pos[i][1]= ny + 4*my;
343                             break;
344                         }
345                     }
346                 }
347             }
348         }else{
349             int tl;
350             const int cx = 4*(r - l);
351             const int cx2= r + l - 2*c; 
352             const int cy = 4*(b - t);
353             const int cy2= b + t - 2*c;
354             int cxy;
355               
356             if(map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)] == (my<<ME_MAP_MV_BITS) + mx + map_generation && 0){ //FIXME
357                 tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
358             }else{
359                 tl= cmp(s, mx-1, my-1, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);//FIXME wrong if chroma me is different
360             }
361             
362             cxy= 2*tl + (cx + cy)/4 - (cx2 + cy2) - 2*c; 
363            
364             assert(16*cx2 + 4*cx + 32*c == 32*r);
365             assert(16*cx2 - 4*cx + 32*c == 32*l);
366             assert(16*cy2 + 4*cy + 32*c == 32*b);
367             assert(16*cy2 - 4*cy + 32*c == 32*t);
368             assert(16*cxy + 16*cy2 + 16*cx2 - 4*cy - 4*cx + 32*c == 32*tl);
369             
370             for(ny= -3; ny <= 3; ny++){
371                 for(nx= -3; nx <= 3; nx++){
372                     int score= ny*nx*cxy + nx*nx*cx2 + ny*ny*cy2 + nx*cx + ny*cy + 32*c; //FIXME factor
373                     int i;
374                     
375                     if((nx&3)==0 && (ny&3)==0) continue;
376                 
377                     score += 32*(mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;
378 //                    if(nx&1) score-=32*s->me.penalty_factor;
379   //                  if(ny&1) score-=32*s->me.penalty_factor;
380                     
381                     for(i=0; i<8; i++){
382                         if(score < best[i]){
383                             memmove(&best[i+1], &best[i], sizeof(int)*(7-i));
384                             memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i));
385                             best[i]= score;
386                             best_pos[i][0]= nx + 4*mx;
387                             best_pos[i][1]= ny + 4*my;
388                             break;
389                         }
390                     }
391                 }
392             }            
393         }
394         for(i=0; i<subpel_quality; i++){
395             nx= best_pos[i][0];
396             ny= best_pos[i][1];
397             CHECK_QUARTER_MV(nx&3, ny&3, nx>>2, ny>>2)
398         }
399
400 #if 0
401             const int tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
402             const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
403             const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
404             const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
405 //            if(l < r && l < t && l < b && l < tl && l < bl && l < tr && l < br && bl < tl){
406             if(tl<br){
407
408 //            nx= FFMAX(4*mx - bx, bx - 4*mx);
409 //            ny= FFMAX(4*my - by, by - 4*my);
410             
411             static int stats[7][7], count;
412             count++;
413             stats[4*mx - bx + 3][4*my - by + 3]++;
414             if(256*256*256*64 % count ==0){
415                 for(i=0; i<49; i++){
416                     if((i%7)==0) printf("\n");
417                     printf("%6d ", stats[0][i]);
418                 }
419                 printf("\n");
420             }
421             }
422 #endif
423 #else
424
425         CHECK_QUARTER_MV(2, 2, mx-1, my-1)
426         CHECK_QUARTER_MV(0, 2, mx  , my-1)        
427         CHECK_QUARTER_MV(2, 2, mx  , my-1)
428         CHECK_QUARTER_MV(2, 0, mx  , my  )
429         CHECK_QUARTER_MV(2, 2, mx  , my  )
430         CHECK_QUARTER_MV(0, 2, mx  , my  )
431         CHECK_QUARTER_MV(2, 2, mx-1, my  )
432         CHECK_QUARTER_MV(2, 0, mx-1, my  )
433         
434         nx= bx;
435         ny= by;
436         
437         for(i=0; i<8; i++){
438             int ox[8]= {0, 1, 1, 1, 0,-1,-1,-1};
439             int oy[8]= {1, 1, 0,-1,-1,-1, 0, 1};
440             CHECK_QUARTER_MV((nx + ox[i])&3, (ny + oy[i])&3, (nx + ox[i])>>2, (ny + oy[i])>>2)
441         }
442 #endif
443 #if 0
444         //outer ring
445         CHECK_QUARTER_MV(1, 3, mx-1, my-1)
446         CHECK_QUARTER_MV(1, 2, mx-1, my-1)
447         CHECK_QUARTER_MV(1, 1, mx-1, my-1)
448         CHECK_QUARTER_MV(2, 1, mx-1, my-1)
449         CHECK_QUARTER_MV(3, 1, mx-1, my-1)
450         CHECK_QUARTER_MV(0, 1, mx  , my-1)
451         CHECK_QUARTER_MV(1, 1, mx  , my-1)
452         CHECK_QUARTER_MV(2, 1, mx  , my-1)
453         CHECK_QUARTER_MV(3, 1, mx  , my-1)
454         CHECK_QUARTER_MV(3, 2, mx  , my-1)
455         CHECK_QUARTER_MV(3, 3, mx  , my-1)
456         CHECK_QUARTER_MV(3, 0, mx  , my  )
457         CHECK_QUARTER_MV(3, 1, mx  , my  )
458         CHECK_QUARTER_MV(3, 2, mx  , my  )
459         CHECK_QUARTER_MV(3, 3, mx  , my  )
460         CHECK_QUARTER_MV(2, 3, mx  , my  )
461         CHECK_QUARTER_MV(1, 3, mx  , my  )
462         CHECK_QUARTER_MV(0, 3, mx  , my  )
463         CHECK_QUARTER_MV(3, 3, mx-1, my  )
464         CHECK_QUARTER_MV(2, 3, mx-1, my  )
465         CHECK_QUARTER_MV(1, 3, mx-1, my  )
466         CHECK_QUARTER_MV(1, 2, mx-1, my  )
467         CHECK_QUARTER_MV(1, 1, mx-1, my  )
468         CHECK_QUARTER_MV(1, 0, mx-1, my  )
469 #endif
470         assert(bx >= xmin*4 && bx <= xmax*4 && by >= ymin*4 && by <= ymax*4);
471
472         *mx_ptr = bx;
473         *my_ptr = by;
474     }else{
475         *mx_ptr =4*mx;
476         *my_ptr =4*my;
477     }
478
479     return dmin;
480 }
481
482
483 #define CHECK_MV(x,y)\
484 {\
485     const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
486     const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
487 /*printf("check_mv %d %d\n", x, y);*/\
488     if(map[index]!=key){\
489         d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
490         map[index]= key;\
491         score_map[index]= d;\
492         d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\
493 /*printf("score:%d\n", d);*/\
494         COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\
495     }\
496 }
497
498 #define CHECK_CLIPED_MV(ax,ay)\
499 {\
500     const int x= ax;\
501     const int y= ay;\
502     const int x2= FFMAX(xmin, FFMIN(x, xmax));\
503     const int y2= FFMAX(ymin, FFMIN(y, ymax));\
504     CHECK_MV(x2, y2)\
505 }
506
507 #define CHECK_MV_DIR(x,y,new_dir)\
508 {\
509     const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
510     const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
511 /*printf("check_mv_dir %d %d %d\n", x, y, new_dir);*/\
512     if(map[index]!=key){\
513         d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
514         map[index]= key;\
515         score_map[index]= d;\
516         d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\
517 /*printf("score:%d\n", d);*/\
518         if(d<dmin){\
519             best[0]=x;\
520             best[1]=y;\
521             dmin=d;\
522             next_dir= new_dir;\
523         }\
524     }\
525 }
526
527 #define check(x,y,S,v)\
528 if( (x)<(xmin<<(S)) ) printf("%d %d %d %d %d xmin" #v, xmin, (x), (y), s->mb_x, s->mb_y);\
529 if( (x)>(xmax<<(S)) ) printf("%d %d %d %d %d xmax" #v, xmax, (x), (y), s->mb_x, s->mb_y);\
530 if( (y)<(ymin<<(S)) ) printf("%d %d %d %d %d ymin" #v, ymin, (x), (y), s->mb_x, s->mb_y);\
531 if( (y)>(ymax<<(S)) ) printf("%d %d %d %d %d ymax" #v, ymax, (x), (y), s->mb_x, s->mb_y);\
532
533 #define LOAD_COMMON2\
534     uint32_t *map= s->me.map;\
535     const int qpel= flags&FLAG_QPEL;\
536     const int shift= 1+qpel;\
537
538 static always_inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
539                                        int src_index, int ref_index, int const penalty_factor,
540                                        int size, int h, int flags)
541 {
542     me_cmp_func cmpf, chroma_cmpf;
543     int next_dir=-1;
544     LOAD_COMMON
545     LOAD_COMMON2
546     int map_generation= s->me.map_generation;
547     
548     cmpf= s->dsp.me_cmp[size];
549     chroma_cmpf= s->dsp.me_cmp[size+1];
550
551     { /* ensure that the best point is in the MAP as h/qpel refinement needs it */
552         const int key= (best[1]<<ME_MAP_MV_BITS) + best[0] + map_generation;
553         const int index= ((best[1]<<ME_MAP_SHIFT) + best[0])&(ME_MAP_SIZE-1);
554         if(map[index]!=key){ //this will be executed only very rarey
555             score_map[index]= cmp(s, best[0], best[1], 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
556             map[index]= key;
557         }
558     }
559
560     for(;;){
561         int d;
562         const int dir= next_dir;
563         const int x= best[0];
564         const int y= best[1];
565         next_dir=-1;
566
567 //printf("%d", dir);
568         if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y  , 0)
569         if(dir!=3 && y>ymin) CHECK_MV_DIR(x  , y-1, 1)
570         if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y  , 2)
571         if(dir!=1 && y<ymax) CHECK_MV_DIR(x  , y+1, 3)
572
573         if(next_dir==-1){
574             return dmin;
575         }
576     }
577 }
578
579 static int funny_diamond_search(MpegEncContext * s, int *best, int dmin,
580                                        int src_index, int ref_index, int const penalty_factor,
581                                        int size, int h, int flags)
582 {
583     me_cmp_func cmpf, chroma_cmpf;
584     int dia_size;
585     LOAD_COMMON
586     LOAD_COMMON2
587     int map_generation= s->me.map_generation;
588     
589     cmpf= s->dsp.me_cmp[size];
590     chroma_cmpf= s->dsp.me_cmp[size+1];
591
592     for(dia_size=1; dia_size<=4; dia_size++){
593         int dir;
594         const int x= best[0];
595         const int y= best[1];
596         
597         if(dia_size&(dia_size-1)) continue;
598
599         if(   x + dia_size > xmax
600            || x - dia_size < xmin
601            || y + dia_size > ymax
602            || y - dia_size < ymin)
603            continue;
604         
605         for(dir= 0; dir<dia_size; dir+=2){
606             int d;
607
608             CHECK_MV(x + dir           , y + dia_size - dir);
609             CHECK_MV(x + dia_size - dir, y - dir           );
610             CHECK_MV(x - dir           , y - dia_size + dir);
611             CHECK_MV(x - dia_size + dir, y + dir           );
612         }
613
614         if(x!=best[0] || y!=best[1])
615             dia_size=0;
616 #if 0
617 {
618 int dx, dy, i;
619 static int stats[8*8];
620 dx= ABS(x-best[0]);
621 dy= ABS(y-best[1]);
622 if(dy>dx){
623     dx^=dy; dy^=dx; dx^=dy;
624 }
625 stats[dy*8 + dx] ++;
626 if(256*256*256*64 % (stats[0]+1)==0){
627     for(i=0; i<64; i++){
628         if((i&7)==0) printf("\n");
629         printf("%8d ", stats[i]);
630     }
631     printf("\n");
632 }
633 }
634 #endif
635     }
636     return dmin;    
637 }
638
639 #define SAB_CHECK_MV(ax,ay)\
640 {\
641     const int key= ((ay)<<ME_MAP_MV_BITS) + (ax) + map_generation;\
642     const int index= (((ay)<<ME_MAP_SHIFT) + (ax))&(ME_MAP_SIZE-1);\
643 /*printf("sab check %d %d\n", ax, ay);*/\
644     if(map[index]!=key){\
645         d= cmp(s, ax, ay, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
646         map[index]= key;\
647         score_map[index]= d;\
648         d += (mv_penalty[((ax)<<shift)-pred_x] + mv_penalty[((ay)<<shift)-pred_y])*penalty_factor;\
649 /*printf("score: %d\n", d);*/\
650         if(d < minima[minima_count-1].height){\
651             int j=0;\
652             \
653             while(d >= minima[j].height) j++;\
654 \
655             memmove(&minima [j+1], &minima [j], (minima_count - j - 1)*sizeof(Minima));\
656 \
657             minima[j].checked= 0;\
658             minima[j].height= d;\
659             minima[j].x= ax;\
660             minima[j].y= ay;\
661             \
662             i=-1;\
663             continue;\
664         }\
665     }\
666 }
667
668 #define MAX_SAB_SIZE 16
669 static int sab_diamond_search(MpegEncContext * s, int *best, int dmin,
670                                        int src_index, int ref_index, int const penalty_factor,
671                                        int size, int h, int flags)
672 {
673     me_cmp_func cmpf, chroma_cmpf;
674     Minima minima[MAX_SAB_SIZE];
675     const int minima_count= ABS(s->me.dia_size);
676     int i, j;
677     LOAD_COMMON
678     LOAD_COMMON2
679     int map_generation= s->me.map_generation;
680     
681     cmpf= s->dsp.me_cmp[size];
682     chroma_cmpf= s->dsp.me_cmp[size+1];
683     
684     for(j=i=0; i<ME_MAP_SIZE; i++){
685         uint32_t key= map[i];
686
687         key += (1<<(ME_MAP_MV_BITS-1)) + (1<<(2*ME_MAP_MV_BITS-1));
688         
689         if((key&((-1)<<(2*ME_MAP_MV_BITS))) != map_generation) continue;
690         
691         assert(j<MAX_SAB_SIZE); //max j = number of predictors
692         
693         minima[j].height= score_map[i];
694         minima[j].x= key & ((1<<ME_MAP_MV_BITS)-1); key>>=ME_MAP_MV_BITS;
695         minima[j].y= key & ((1<<ME_MAP_MV_BITS)-1);
696         minima[j].x-= (1<<(ME_MAP_MV_BITS-1));
697         minima[j].y-= (1<<(ME_MAP_MV_BITS-1));
698         minima[j].checked=0;
699         if(minima[j].x || minima[j].y)
700             minima[j].height+= (mv_penalty[((minima[j].x)<<shift)-pred_x] + mv_penalty[((minima[j].y)<<shift)-pred_y])*penalty_factor;
701         
702         j++;
703     }
704     
705     qsort(minima, j, sizeof(Minima), minima_cmp);
706     
707     for(; j<minima_count; j++){
708         minima[j].height=256*256*256*64;
709         minima[j].checked=0;
710         minima[j].x= minima[j].y=0;
711     }
712     
713     for(i=0; i<minima_count; i++){
714         const int x= minima[i].x;
715         const int y= minima[i].y;
716         int d;
717         
718         if(minima[i].checked) continue;
719         
720         if(   x >= xmax || x <= xmin
721            || y >= ymax || y <= ymin)
722            continue;
723
724         SAB_CHECK_MV(x-1, y)
725         SAB_CHECK_MV(x+1, y)
726         SAB_CHECK_MV(x  , y-1)
727         SAB_CHECK_MV(x  , y+1)
728         
729         minima[i].checked= 1;
730     }
731     
732     best[0]= minima[0].x;
733     best[1]= minima[0].y;
734     dmin= minima[0].height;
735     
736     if(   best[0] < xmax && best[0] > xmin
737        && best[1] < ymax && best[1] > ymin){
738         int d;
739         //ensure that the refernece samples for hpel refinement are in the map
740         CHECK_MV(best[0]-1, best[1])
741         CHECK_MV(best[0]+1, best[1])
742         CHECK_MV(best[0], best[1]-1)
743         CHECK_MV(best[0], best[1]+1)
744     }
745     return dmin;    
746 }
747
748 static int var_diamond_search(MpegEncContext * s, int *best, int dmin,
749                                        int src_index, int ref_index, int const penalty_factor,
750                                        int size, int h, int flags)
751 {
752     me_cmp_func cmpf, chroma_cmpf;
753     int dia_size;
754     LOAD_COMMON
755     LOAD_COMMON2
756     int map_generation= s->me.map_generation;
757     
758     cmpf= s->dsp.me_cmp[size];
759     chroma_cmpf= s->dsp.me_cmp[size+1];
760
761     for(dia_size=1; dia_size<=s->me.dia_size; dia_size++){
762         int dir, start, end;
763         const int x= best[0];
764         const int y= best[1];
765
766         start= FFMAX(0, y + dia_size - ymax);
767         end  = FFMIN(dia_size, xmax - x + 1);
768         for(dir= start; dir<end; dir++){
769             int d;
770
771 //check(x + dir,y + dia_size - dir,0, a0)
772             CHECK_MV(x + dir           , y + dia_size - dir);
773         }
774
775         start= FFMAX(0, x + dia_size - xmax);
776         end  = FFMIN(dia_size, y - ymin + 1);
777         for(dir= start; dir<end; dir++){
778             int d;
779
780 //check(x + dia_size - dir, y - dir,0, a1)
781             CHECK_MV(x + dia_size - dir, y - dir           );
782         }
783
784         start= FFMAX(0, -y + dia_size + ymin );
785         end  = FFMIN(dia_size, x - xmin + 1);
786         for(dir= start; dir<end; dir++){
787             int d;
788
789 //check(x - dir,y - dia_size + dir,0, a2)
790             CHECK_MV(x - dir           , y - dia_size + dir);
791         }
792
793         start= FFMAX(0, -x + dia_size + xmin );
794         end  = FFMIN(dia_size, ymax - y + 1);
795         for(dir= start; dir<end; dir++){
796             int d;
797
798 //check(x - dia_size + dir, y + dir,0, a3)
799             CHECK_MV(x - dia_size + dir, y + dir           );
800         }
801
802         if(x!=best[0] || y!=best[1])
803             dia_size=0;
804 #if 0
805 {
806 int dx, dy, i;
807 static int stats[8*8];
808 dx= ABS(x-best[0]);
809 dy= ABS(y-best[1]);
810 stats[dy*8 + dx] ++;
811 if(256*256*256*64 % (stats[0]+1)==0){
812     for(i=0; i<64; i++){
813         if((i&7)==0) printf("\n");
814         printf("%6d ", stats[i]);
815     }
816     printf("\n");
817 }
818 }
819 #endif
820     }
821     return dmin;    
822 }
823
824 static always_inline int diamond_search(MpegEncContext * s, int *best, int dmin,
825                                        int src_index, int ref_index, int const penalty_factor,
826                                        int size, int h, int flags){
827     if(s->me.dia_size==-1)
828         return funny_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
829     else if(s->me.dia_size<-1)
830         return   sab_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
831     else if(s->me.dia_size<2)
832         return small_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
833     else
834         return   var_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
835 }
836
837 static always_inline int epzs_motion_search_internal(MpegEncContext * s, int *mx_ptr, int *my_ptr,
838                              int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2], 
839                              int ref_mv_scale, int flags)
840 {
841     int best[2]={0, 0};
842     int d, dmin;
843     int map_generation;
844     const int penalty_factor= s->me.penalty_factor;
845     const int size=0;
846     const int h=16;
847     const int ref_mv_stride= s->mb_stride; //pass as arg  FIXME
848     const int ref_mv_xy= s->mb_x + s->mb_y*ref_mv_stride; //add to last_mv beforepassing FIXME
849     me_cmp_func cmpf, chroma_cmpf;
850     
851     LOAD_COMMON
852     LOAD_COMMON2
853     
854     cmpf= s->dsp.me_cmp[size];
855     chroma_cmpf= s->dsp.me_cmp[size+1];
856     
857     map_generation= update_map_generation(s);
858
859     dmin= cmp(s, 0, 0, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
860     map[0]= map_generation;
861     score_map[0]= dmin;
862
863     /* first line */
864     if (s->first_slice_line) {
865         CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
866         CHECK_CLIPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, 
867                         (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
868     }else{
869         if(dmin<256 && ( P_LEFT[0]    |P_LEFT[1]
870                         |P_TOP[0]     |P_TOP[1]
871                         |P_TOPRIGHT[0]|P_TOPRIGHT[1])==0){
872             *mx_ptr= 0;
873             *my_ptr= 0;
874             s->me.skip=1;
875             return dmin;
876         }
877         CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)
878         if(dmin>256*2){
879             CHECK_CLIPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, 
880                             (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
881             CHECK_MV(P_LEFT[0]    >>shift, P_LEFT[1]    >>shift)
882             CHECK_MV(P_TOP[0]     >>shift, P_TOP[1]     >>shift)
883             CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
884         }
885     }
886     if(dmin>256*4){
887         if(s->me.pre_pass){
888             CHECK_CLIPED_MV((last_mv[ref_mv_xy-1][0]*ref_mv_scale + (1<<15))>>16, 
889                             (last_mv[ref_mv_xy-1][1]*ref_mv_scale + (1<<15))>>16)
890             if(!s->first_slice_line)
891                 CHECK_CLIPED_MV((last_mv[ref_mv_xy-ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16, 
892                                 (last_mv[ref_mv_xy-ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
893         }else{
894             CHECK_CLIPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16, 
895                             (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
896             if(s->mb_y+1<s->end_mb_y)  //FIXME replace at least with last_slice_line
897                 CHECK_CLIPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16, 
898                                 (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
899         }
900     }
901
902     if(s->avctx->last_predictor_count){
903         const int count= s->avctx->last_predictor_count;
904         const int xstart= FFMAX(0, s->mb_x - count);
905         const int ystart= FFMAX(0, s->mb_y - count);
906         const int xend= FFMIN(s->mb_width , s->mb_x + count + 1);
907         const int yend= FFMIN(s->mb_height, s->mb_y + count + 1);
908         int mb_y;
909
910         for(mb_y=ystart; mb_y<yend; mb_y++){
911             int mb_x;
912             for(mb_x=xstart; mb_x<xend; mb_x++){
913                 const int xy= mb_x + 1 + (mb_y + 1)*ref_mv_stride;
914                 int mx= (last_mv[xy][0]*ref_mv_scale + (1<<15))>>16;
915                 int my= (last_mv[xy][1]*ref_mv_scale + (1<<15))>>16;
916
917                 if(mx>xmax || mx<xmin || my>ymax || my<ymin) continue;
918                 CHECK_MV(mx,my)
919             }
920         }
921     }
922
923 //check(best[0],best[1],0, b0)
924     dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
925
926 //check(best[0],best[1],0, b1)
927     *mx_ptr= best[0];
928     *my_ptr= best[1];    
929
930 //    printf("%d %d %d \n", best[0], best[1], dmin);
931     return dmin;
932 }
933
934 //this function is dedicated to the braindamaged gcc
935 static inline int epzs_motion_search(MpegEncContext * s, int *mx_ptr, int *my_ptr,
936                              int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2], 
937                              int ref_mv_scale)
938 {
939 //FIXME convert other functions in the same way if faster
940     switch(s->me.flags){
941     case 0:
942         return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, 0);
943 //    case FLAG_QPEL:
944 //        return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, FLAG_QPEL);
945     default:
946         return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, s->me.flags);
947     }
948 }
949
950 static int epzs_motion_search4(MpegEncContext * s,
951                              int *mx_ptr, int *my_ptr, int P[10][2],
952                              int src_index, int ref_index, int16_t (*last_mv)[2], 
953                              int ref_mv_scale)
954 {
955     int best[2]={0, 0};
956     int d, dmin; 
957     int map_generation;
958     const int penalty_factor= s->me.penalty_factor;
959     const int size=1;
960     const int h=8;
961     const int ref_mv_stride= s->mb_stride;
962     const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride;
963     me_cmp_func cmpf, chroma_cmpf;
964     LOAD_COMMON
965     int flags= s->me.flags;
966     LOAD_COMMON2
967     
968     cmpf= s->dsp.me_cmp[size];
969     chroma_cmpf= s->dsp.me_cmp[size+1];
970
971     map_generation= update_map_generation(s);
972
973     dmin = 1000000;
974 //printf("%d %d %d %d //",xmin, ymin, xmax, ymax); 
975     /* first line */
976     if (s->first_slice_line) {
977         CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
978         CHECK_CLIPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, 
979                         (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
980         CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
981     }else{
982         CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
983         //FIXME try some early stop
984         if(dmin>64*2){
985             CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)
986             CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
987             CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift)
988             CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
989             CHECK_CLIPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, 
990                             (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
991         }
992     }
993     if(dmin>64*4){
994         CHECK_CLIPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16, 
995                         (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
996         if(s->mb_y+1<s->end_mb_y)  //FIXME replace at least with last_slice_line
997             CHECK_CLIPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16, 
998                             (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
999     }
1000
1001     dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
1002
1003     *mx_ptr= best[0];
1004     *my_ptr= best[1];    
1005
1006 //    printf("%d %d %d \n", best[0], best[1], dmin);
1007     return dmin;
1008 }
1009
1010 //try to merge with above FIXME (needs PSNR test)
1011 static int epzs_motion_search2(MpegEncContext * s,
1012                              int *mx_ptr, int *my_ptr, int P[10][2],
1013                              int src_index, int ref_index, int16_t (*last_mv)[2], 
1014                              int ref_mv_scale)
1015 {
1016     int best[2]={0, 0};
1017     int d, dmin; 
1018     int map_generation;
1019     const int penalty_factor= s->me.penalty_factor;
1020     const int size=0; //FIXME pass as arg
1021     const int h=8;
1022     const int ref_mv_stride= s->mb_stride;
1023     const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride;
1024     me_cmp_func cmpf, chroma_cmpf;
1025     LOAD_COMMON
1026     int flags= s->me.flags;
1027     LOAD_COMMON2
1028     
1029     cmpf= s->dsp.me_cmp[size];
1030     chroma_cmpf= s->dsp.me_cmp[size+1];
1031
1032     map_generation= update_map_generation(s);
1033
1034     dmin = 1000000;
1035 //printf("%d %d %d %d //",xmin, ymin, xmax, ymax); 
1036     /* first line */
1037     if (s->first_slice_line) {
1038         CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1039         CHECK_CLIPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, 
1040                         (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1041         CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
1042     }else{
1043         CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
1044         //FIXME try some early stop
1045         if(dmin>64*2){
1046             CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)
1047             CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1048             CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift)
1049             CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
1050             CHECK_CLIPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, 
1051                             (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1052         }
1053     }
1054     if(dmin>64*4){
1055         CHECK_CLIPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16, 
1056                         (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
1057         if(s->mb_y+1<s->end_mb_y)  //FIXME replace at least with last_slice_line
1058             CHECK_CLIPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16, 
1059                             (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
1060     }
1061
1062     dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
1063
1064     *mx_ptr= best[0];
1065     *my_ptr= best[1];    
1066
1067 //    printf("%d %d %d \n", best[0], best[1], dmin);
1068     return dmin;
1069 }