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