3 * Copyright (c) 2002-2004 Michael Niedermayer
5 * This file is part of FFmpeg.
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.
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.
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
24 * Motion estimation template.
27 //Let us hope gcc will remove the unused vars ...(gcc 3.2.2 seems to do it ...)
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;\
38 #define CHECK_HALF_MV(dx, dy, x, y)\
40 const int hx= 2*(x)+(dx);\
41 const int hy= 2*(y)+(dy);\
42 d= cmp_hpel(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)\
48 static int hpel_motion_search)(MpegEncContext * s,
49 int *mx_ptr, int *my_ptr, int dmin,
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;
63 me_cmp_func cmp, chroma_cmp, cmp_sub, chroma_cmp_sub;
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];
69 hpel_put=& s->dsp.put_pixels_tab[size];
70 chroma_hpel_put= &s->dsp.put_pixels_tab[size+1];
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];
77 if(c->skip){ //FIXME somehow move up (benchmark)
83 if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
84 CMP_HPEL(dmin, 0, 0, mx, my, size);
86 dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor;
89 if (mx > xmin && mx < xmax &&
90 my > ymin && my < ymax) {
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 )
103 assert(bx >= xmin*2 || bx <= xmax*2 || by >= ymin*2 || by <= ymax*2);
116 static int hpel_motion_search(MpegEncContext * s,
117 int *mx_ptr, int *my_ptr, int dmin,
118 int src_index, int ref_index,
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;
129 int flags= c->sub_flags;
133 cmp_sub= s->dsp.me_sub_cmp[size];
134 chroma_cmp_sub= s->dsp.me_sub_cmp[size+1];
136 if(c->skip){ //FIXME move out of hpel?
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;
148 if (mx > xmin && mx < xmax &&
149 my > ymin && my < ymax) {
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;
163 int map_generation= c->map_generation;
165 uint32_t *map= c->map;
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);
177 CHECK_HALF_MV(0, 1, mx ,my-1)
179 CHECK_HALF_MV(1, 1, mx-1, my-1)
181 CHECK_HALF_MV(1, 1, mx , my-1)
183 CHECK_HALF_MV(1, 1, mx-1, my )
185 CHECK_HALF_MV(1, 0, mx-1, my )
187 CHECK_HALF_MV(1, 1, mx , my-1)
189 CHECK_HALF_MV(1, 1, mx-1, my-1)
191 CHECK_HALF_MV(1, 1, mx , my )
193 CHECK_HALF_MV(1, 0, mx , my )
198 CHECK_HALF_MV(1, 1, mx-1, my-1)
200 CHECK_HALF_MV(1, 1, mx , my )
202 CHECK_HALF_MV(1, 0, mx-1, my)
203 CHECK_HALF_MV(1, 1, mx-1, my)
206 CHECK_HALF_MV(1, 1, mx , my-1)
208 CHECK_HALF_MV(1, 1, mx-1, my)
210 CHECK_HALF_MV(1, 0, mx , my)
211 CHECK_HALF_MV(1, 1, mx , my)
213 CHECK_HALF_MV(0, 1, mx , my)
215 assert(bx >= xmin*2 && bx <= xmax*2 && by >= ymin*2 && by <= ymax*2);
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,
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)
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;
251 cmp_sub= s->dsp.mb_cmp[size];
252 chroma_cmp_sub= s->dsp.mb_cmp[size+1];
255 // assert(c->avctx->me_sub_cmp != c->avctx->mb_cmp);
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;
265 #define CHECK_QUARTER_MV(dx, dy, x, y)\
267 const int hx= 4*(x)+(dx);\
268 const int hy= 4*(y)+(dy);\
269 d= cmp_qpel(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)\
274 static int qpel_motion_search(MpegEncContext * s,
275 int *mx_ptr, int *my_ptr, int dmin,
276 int src_index, int ref_index,
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;
290 int flags= c->sub_flags;
292 cmpf= s->dsp.me_cmp[size];
293 chroma_cmpf= s->dsp.me_cmp[size+1]; //factorize FIXME
296 cmp_sub= s->dsp.me_sub_cmp[size];
297 chroma_cmp_sub= s->dsp.me_sub_cmp[size+1];
299 if(c->skip){ //FIXME somehow move up (benchmark)
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;
311 if (mx > xmin && mx < xmax &&
312 my > ymin && my < ymax) {
313 int bx=4*mx, by=4*my;
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)];
325 memset(best, 64, sizeof(int)*8);
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)];
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;
342 if((nx&3)==0 && (ny&3)==0) continue;
344 score += (mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;
346 // if(nx&1) score-=1024*c->penalty_factor;
347 // if(ny&1) score-=1024*c->penalty_factor;
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));
354 best_pos[i][0]= nx + 4*mx;
355 best_pos[i][1]= ny + 4*my;
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;
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)];
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
376 cxy= 2*tl + (cx + cy)/4 - (cx2 + cy2) - 2*c;
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);
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
390 if((nx&3)==0 && (ny&3)==0) continue;
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;
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));
401 best_pos[i][0]= nx + 4*mx;
402 best_pos[i][1]= ny + 4*my;
409 for(i=0; i<subpel_quality; i++){
412 CHECK_QUARTER_MV(nx&3, ny&3, nx>>2, ny>>2)
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){
423 // nx= FFMAX(4*mx - bx, bx - 4*mx);
424 // ny= FFMAX(4*my - by, by - 4*my);
426 static int stats[7][7], count;
428 stats[4*mx - bx + 3][4*my - by + 3]++;
429 if(256*256*256*64 % count ==0){
431 if((i%7)==0) printf("\n");
432 printf("%6d ", stats[0][i]);
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 )
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)
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 )
485 assert(bx >= xmin*4 && bx <= xmax*4 && by >= ymin*4 && by <= ymax*4);
498 #define CHECK_MV(x,y)\
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);\
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)\
517 #define CHECK_CLIPPED_MV(ax,ay)\
521 const int Lx2= FFMAX(xmin, FFMIN(Lx, xmax));\
522 const int Ly2= FFMAX(ymin, FFMIN(Ly, ymax));\
526 #define CHECK_MV_DIR(x,y,new_dir)\
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);\
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);*/\
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);\
552 #define LOAD_COMMON2\
553 uint32_t *map= c->map;\
554 const int qpel= flags&FLAG_QPEL;\
555 const int shift= 1+qpel;\
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)
561 MotionEstContext * const c= &s->me;
562 me_cmp_func cmpf, chroma_cmpf;
566 int map_generation= c->map_generation;
568 cmpf= s->dsp.me_cmp[size];
569 chroma_cmpf= s->dsp.me_cmp[size+1];
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);
582 const int dir= next_dir;
583 const int x= best[0];
584 const int y= best[1];
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)
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)
603 MotionEstContext * const c= &s->me;
604 me_cmp_func cmpf, chroma_cmpf;
608 int map_generation= c->map_generation;
610 cmpf= s->dsp.me_cmp[size];
611 chroma_cmpf= s->dsp.me_cmp[size+1];
613 for(dia_size=1; dia_size<=4; dia_size++){
615 const int x= best[0];
616 const int y= best[1];
618 if(dia_size&(dia_size-1)) continue;
620 if( x + dia_size > xmax
621 || x - dia_size < xmin
622 || y + dia_size > ymax
623 || y - dia_size < ymin)
626 for(dir= 0; dir<dia_size; dir+=2){
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 );
635 if(x!=best[0] || y!=best[1])
641 static int hex_search(MpegEncContext * s, int *best, int dmin,
642 int src_index, int ref_index, int const penalty_factor,
643 int size, int h, int flags, int dia_size)
645 MotionEstContext * const c= &s->me;
646 me_cmp_func cmpf, chroma_cmpf;
649 int map_generation= c->map_generation;
651 const int dec= dia_size & (dia_size-1);
653 cmpf= s->dsp.me_cmp[size];
654 chroma_cmpf= s->dsp.me_cmp[size+1];
656 for(;dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){
661 CHECK_CLIPPED_MV(x -dia_size , y);
662 CHECK_CLIPPED_MV(x+ dia_size , y);
663 CHECK_CLIPPED_MV(x+( dia_size>>1), y+dia_size);
664 CHECK_CLIPPED_MV(x+( dia_size>>1), y-dia_size);
666 CHECK_CLIPPED_MV(x+(-dia_size>>1), y+dia_size);
667 CHECK_CLIPPED_MV(x+(-dia_size>>1), y-dia_size);
669 }while(best[0] != x || best[1] != y);
675 static int l2s_dia_search(MpegEncContext * s, int *best, int dmin,
676 int src_index, int ref_index, int const penalty_factor,
677 int size, int h, int flags)
679 MotionEstContext * const c= &s->me;
680 me_cmp_func cmpf, chroma_cmpf;
683 int map_generation= c->map_generation;
685 int dia_size= c->dia_size&0xFF;
686 const int dec= dia_size & (dia_size-1);
687 static const int hex[8][2]={{-2, 0}, {-1,-1}, { 0,-2}, { 1,-1},
688 { 2, 0}, { 1, 1}, { 0, 2}, {-1, 1}};
690 cmpf= s->dsp.me_cmp[size];
691 chroma_cmpf= s->dsp.me_cmp[size+1];
693 for(; dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){
698 CHECK_CLIPPED_MV(x+hex[i][0]*dia_size, y+hex[i][1]*dia_size);
700 }while(best[0] != x || best[1] != y);
705 CHECK_CLIPPED_MV(x+1, y);
706 CHECK_CLIPPED_MV(x, y+1);
707 CHECK_CLIPPED_MV(x-1, y);
708 CHECK_CLIPPED_MV(x, y-1);
713 static int umh_search(MpegEncContext * s, int *best, int dmin,
714 int src_index, int ref_index, int const penalty_factor,
715 int size, int h, int flags)
717 MotionEstContext * const c= &s->me;
718 me_cmp_func cmpf, chroma_cmpf;
721 int map_generation= c->map_generation;
722 int x,y,x2,y2, i, j, d;
723 const int dia_size= c->dia_size&0xFE;
724 static const int hex[16][2]={{-4,-2}, {-4,-1}, {-4, 0}, {-4, 1}, {-4, 2},
725 { 4,-2}, { 4,-1}, { 4, 0}, { 4, 1}, { 4, 2},
726 {-2, 3}, { 0, 4}, { 2, 3},
727 {-2,-3}, { 0,-4}, { 2,-3},};
729 cmpf= s->dsp.me_cmp[size];
730 chroma_cmpf= s->dsp.me_cmp[size+1];
734 for(x2=FFMAX(x-dia_size+1, xmin); x2<=FFMIN(x+dia_size-1,xmax); x2+=2){
737 for(y2=FFMAX(y-dia_size/2+1, ymin); y2<=FFMIN(y+dia_size/2-1,ymax); y2+=2){
743 for(y2=FFMAX(y-2, ymin); y2<=FFMIN(y+2,ymax); y2++){
744 for(x2=FFMAX(x-2, xmin); x2<=FFMIN(x+2,xmax); x2++){
749 //FIXME prevent the CLIP stuff
751 for(j=1; j<=dia_size/4; j++){
753 CHECK_CLIPPED_MV(x+hex[i][0]*j, y+hex[i][1]*j);
757 return hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, 2);
760 static int full_search(MpegEncContext * s, int *best, int dmin,
761 int src_index, int ref_index, int const penalty_factor,
762 int size, int h, int flags)
764 MotionEstContext * const c= &s->me;
765 me_cmp_func cmpf, chroma_cmpf;
768 int map_generation= c->map_generation;
770 const int dia_size= c->dia_size&0xFF;
772 cmpf= s->dsp.me_cmp[size];
773 chroma_cmpf= s->dsp.me_cmp[size+1];
775 for(y=FFMAX(-dia_size, ymin); y<=FFMIN(dia_size,ymax); y++){
776 for(x=FFMAX(-dia_size, xmin); x<=FFMIN(dia_size,xmax); x++){
784 CHECK_CLIPPED_MV(x , y);
785 CHECK_CLIPPED_MV(x+1, y);
786 CHECK_CLIPPED_MV(x, y+1);
787 CHECK_CLIPPED_MV(x-1, y);
788 CHECK_CLIPPED_MV(x, y-1);
795 #define SAB_CHECK_MV(ax,ay)\
797 const int key= ((ay)<<ME_MAP_MV_BITS) + (ax) + map_generation;\
798 const int index= (((ay)<<ME_MAP_SHIFT) + (ax))&(ME_MAP_SIZE-1);\
799 /*printf("sab check %d %d\n", ax, ay);*/\
800 if(map[index]!=key){\
801 d= cmp(s, ax, ay, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
803 score_map[index]= d;\
804 d += (mv_penalty[((ax)<<shift)-pred_x] + mv_penalty[((ay)<<shift)-pred_y])*penalty_factor;\
805 /*printf("score: %d\n", d);*/\
806 if(d < minima[minima_count-1].height){\
809 while(d >= minima[j].height) j++;\
811 memmove(&minima [j+1], &minima [j], (minima_count - j - 1)*sizeof(Minima));\
813 minima[j].checked= 0;\
814 minima[j].height= d;\
824 #define MAX_SAB_SIZE ME_MAP_SIZE
825 static int sab_diamond_search(MpegEncContext * s, int *best, int dmin,
826 int src_index, int ref_index, int const penalty_factor,
827 int size, int h, int flags)
829 MotionEstContext * const c= &s->me;
830 me_cmp_func cmpf, chroma_cmpf;
831 Minima minima[MAX_SAB_SIZE];
832 const int minima_count= FFABS(c->dia_size);
836 int map_generation= c->map_generation;
838 cmpf= s->dsp.me_cmp[size];
839 chroma_cmpf= s->dsp.me_cmp[size+1];
841 /*Note j<MAX_SAB_SIZE is needed if MAX_SAB_SIZE < ME_MAP_SIZE as j can
842 become larger due to MVs overflowing their ME_MAP_MV_BITS bits space in map
844 for(j=i=0; i<ME_MAP_SIZE && j<MAX_SAB_SIZE; i++){
845 uint32_t key= map[i];
847 key += (1<<(ME_MAP_MV_BITS-1)) + (1<<(2*ME_MAP_MV_BITS-1));
849 if((key&((-1)<<(2*ME_MAP_MV_BITS))) != map_generation) continue;
851 minima[j].height= score_map[i];
852 minima[j].x= key & ((1<<ME_MAP_MV_BITS)-1); key>>=ME_MAP_MV_BITS;
853 minima[j].y= key & ((1<<ME_MAP_MV_BITS)-1);
854 minima[j].x-= (1<<(ME_MAP_MV_BITS-1));
855 minima[j].y-= (1<<(ME_MAP_MV_BITS-1));
857 // all entries in map should be in range except if the mv overflows their ME_MAP_MV_BITS bits space
858 if( minima[j].x > xmax || minima[j].x < xmin
859 || minima[j].y > ymax || minima[j].y < ymin)
863 if(minima[j].x || minima[j].y)
864 minima[j].height+= (mv_penalty[((minima[j].x)<<shift)-pred_x] + mv_penalty[((minima[j].y)<<shift)-pred_y])*penalty_factor;
869 qsort(minima, j, sizeof(Minima), minima_cmp);
871 for(; j<minima_count; j++){
872 minima[j].height=256*256*256*64;
874 minima[j].x= minima[j].y=0;
877 for(i=0; i<minima_count; i++){
878 const int x= minima[i].x;
879 const int y= minima[i].y;
882 if(minima[i].checked) continue;
884 if( x >= xmax || x <= xmin
885 || y >= ymax || y <= ymin)
890 SAB_CHECK_MV(x , y-1)
891 SAB_CHECK_MV(x , y+1)
893 minima[i].checked= 1;
896 best[0]= minima[0].x;
897 best[1]= minima[0].y;
898 dmin= minima[0].height;
900 if( best[0] < xmax && best[0] > xmin
901 && best[1] < ymax && best[1] > ymin){
903 //ensure that the refernece samples for hpel refinement are in the map
904 CHECK_MV(best[0]-1, best[1])
905 CHECK_MV(best[0]+1, best[1])
906 CHECK_MV(best[0], best[1]-1)
907 CHECK_MV(best[0], best[1]+1)
912 static int var_diamond_search(MpegEncContext * s, int *best, int dmin,
913 int src_index, int ref_index, int const penalty_factor,
914 int size, int h, int flags)
916 MotionEstContext * const c= &s->me;
917 me_cmp_func cmpf, chroma_cmpf;
921 int map_generation= c->map_generation;
923 cmpf= s->dsp.me_cmp[size];
924 chroma_cmpf= s->dsp.me_cmp[size+1];
926 for(dia_size=1; dia_size<=c->dia_size; dia_size++){
928 const int x= best[0];
929 const int y= best[1];
931 start= FFMAX(0, y + dia_size - ymax);
932 end = FFMIN(dia_size, xmax - x + 1);
933 for(dir= start; dir<end; dir++){
936 //check(x + dir,y + dia_size - dir,0, a0)
937 CHECK_MV(x + dir , y + dia_size - dir);
940 start= FFMAX(0, x + dia_size - xmax);
941 end = FFMIN(dia_size, y - ymin + 1);
942 for(dir= start; dir<end; dir++){
945 //check(x + dia_size - dir, y - dir,0, a1)
946 CHECK_MV(x + dia_size - dir, y - dir );
949 start= FFMAX(0, -y + dia_size + ymin );
950 end = FFMIN(dia_size, x - xmin + 1);
951 for(dir= start; dir<end; dir++){
954 //check(x - dir,y - dia_size + dir,0, a2)
955 CHECK_MV(x - dir , y - dia_size + dir);
958 start= FFMAX(0, -x + dia_size + xmin );
959 end = FFMIN(dia_size, ymax - y + 1);
960 for(dir= start; dir<end; dir++){
963 //check(x - dia_size + dir, y + dir,0, a3)
964 CHECK_MV(x - dia_size + dir, y + dir );
967 if(x!=best[0] || y!=best[1])
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;
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>1024)
984 return full_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
985 else if(c->dia_size>768)
986 return umh_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
987 else if(c->dia_size>512)
988 return hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, c->dia_size&0xFF);
989 else if(c->dia_size>256)
990 return l2s_dia_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
992 return var_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
996 \param P[10][2] a list of candidate mvs to check before starting the
997 iterative search. If one of the candidates is close to the optimal mv, then
998 it takes fewer iterations. And it increases the chance that we find the
1001 static av_always_inline int epzs_motion_search_internal(MpegEncContext * s, int *mx_ptr, int *my_ptr,
1002 int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2],
1003 int ref_mv_scale, int flags, int size, int h)
1005 MotionEstContext * const c= &s->me;
1006 int best[2]={0, 0}; /*!< x and y coordinates of the best motion vector.
1007 i.e. the difference between the position of the
1008 block currently being encoded and the position of
1009 the block chosen to predict it from. */
1010 int d; ///< the score (cmp + penalty) of any given mv
1011 int dmin; /*!< the best value of d, i.e. the score
1012 corresponding to the mv stored in best[]. */
1015 const int ref_mv_stride= s->mb_stride; //pass as arg FIXME
1016 const int ref_mv_xy= s->mb_x + s->mb_y*ref_mv_stride; //add to last_mv beforepassing FIXME
1017 me_cmp_func cmpf, chroma_cmpf;
1023 penalty_factor= c->pre_penalty_factor;
1024 cmpf= s->dsp.me_pre_cmp[size];
1025 chroma_cmpf= s->dsp.me_pre_cmp[size+1];
1027 penalty_factor= c->penalty_factor;
1028 cmpf= s->dsp.me_cmp[size];
1029 chroma_cmpf= s->dsp.me_cmp[size+1];
1032 map_generation= update_map_generation(c);
1035 dmin= cmp(s, 0, 0, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
1036 map[0]= map_generation;
1039 //FIXME precalc first term below?
1040 if((s->pict_type == AV_PICTURE_TYPE_B && !(c->flags & FLAG_DIRECT)) || s->flags&CODEC_FLAG_MV0)
1041 dmin += (mv_penalty[pred_x] + mv_penalty[pred_y])*penalty_factor;
1044 if (s->first_slice_line) {
1045 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1046 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1047 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1049 if(dmin<((h*h*s->avctx->mv0_threshold)>>8)
1050 && ( P_LEFT[0] |P_LEFT[1]
1052 |P_TOPRIGHT[0]|P_TOPRIGHT[1])==0){
1058 CHECK_MV( P_MEDIAN[0] >>shift , P_MEDIAN[1] >>shift)
1059 CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift) , (P_MEDIAN[1]>>shift)-1)
1060 CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift) , (P_MEDIAN[1]>>shift)+1)
1061 CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)-1, (P_MEDIAN[1]>>shift) )
1062 CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)+1, (P_MEDIAN[1]>>shift) )
1063 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1064 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1065 CHECK_MV(P_LEFT[0] >>shift, P_LEFT[1] >>shift)
1066 CHECK_MV(P_TOP[0] >>shift, P_TOP[1] >>shift)
1067 CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
1071 CHECK_CLIPPED_MV((last_mv[ref_mv_xy-1][0]*ref_mv_scale + (1<<15))>>16,
1072 (last_mv[ref_mv_xy-1][1]*ref_mv_scale + (1<<15))>>16)
1073 if(!s->first_slice_line)
1074 CHECK_CLIPPED_MV((last_mv[ref_mv_xy-ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
1075 (last_mv[ref_mv_xy-ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
1077 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
1078 (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
1079 if(s->mb_y+1<s->end_mb_y) //FIXME replace at least with last_slice_line
1080 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
1081 (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
1085 if(c->avctx->last_predictor_count){
1086 const int count= c->avctx->last_predictor_count;
1087 const int xstart= FFMAX(0, s->mb_x - count);
1088 const int ystart= FFMAX(0, s->mb_y - count);
1089 const int xend= FFMIN(s->mb_width , s->mb_x + count + 1);
1090 const int yend= FFMIN(s->mb_height, s->mb_y + count + 1);
1093 for(mb_y=ystart; mb_y<yend; mb_y++){
1095 for(mb_x=xstart; mb_x<xend; mb_x++){
1096 const int xy= mb_x + 1 + (mb_y + 1)*ref_mv_stride;
1097 int mx= (last_mv[xy][0]*ref_mv_scale + (1<<15))>>16;
1098 int my= (last_mv[xy][1]*ref_mv_scale + (1<<15))>>16;
1100 if(mx>xmax || mx<xmin || my>ymax || my<ymin) continue;
1106 //check(best[0],best[1],0, b0)
1107 dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
1109 //check(best[0],best[1],0, b1)
1113 // printf("%d %d %d \n", best[0], best[1], dmin);
1117 //this function is dedicated to the braindamaged gcc
1118 inline int ff_epzs_motion_search(MpegEncContext * s, int *mx_ptr, int *my_ptr,
1119 int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2],
1120 int ref_mv_scale, int size, int h)
1122 MotionEstContext * const c= &s->me;
1123 //FIXME convert other functions in the same way if faster
1124 if(c->flags==0 && h==16 && size==0){
1125 return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, 0, 0, 16);
1127 // return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, FLAG_QPEL);
1129 return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, c->flags, size, h);
1133 static int epzs_motion_search4(MpegEncContext * s,
1134 int *mx_ptr, int *my_ptr, int P[10][2],
1135 int src_index, int ref_index, int16_t (*last_mv)[2],
1138 MotionEstContext * const c= &s->me;
1142 const int penalty_factor= c->penalty_factor;
1145 const int ref_mv_stride= s->mb_stride;
1146 const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride;
1147 me_cmp_func cmpf, chroma_cmpf;
1149 int flags= c->flags;
1152 cmpf= s->dsp.me_cmp[size];
1153 chroma_cmpf= s->dsp.me_cmp[size+1];
1155 map_generation= update_map_generation(c);
1158 //printf("%d %d %d %d //",xmin, ymin, xmax, ymax);
1160 if (s->first_slice_line) {
1161 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1162 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1163 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1164 CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
1166 CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
1167 //FIXME try some early stop
1168 CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)
1169 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1170 CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift)
1171 CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
1172 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1173 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1176 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
1177 (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
1178 if(s->mb_y+1<s->end_mb_y) //FIXME replace at least with last_slice_line
1179 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
1180 (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
1183 dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
1188 // printf("%d %d %d \n", best[0], best[1], dmin);
1192 //try to merge with above FIXME (needs PSNR test)
1193 static int epzs_motion_search2(MpegEncContext * s,
1194 int *mx_ptr, int *my_ptr, int P[10][2],
1195 int src_index, int ref_index, int16_t (*last_mv)[2],
1198 MotionEstContext * const c= &s->me;
1202 const int penalty_factor= c->penalty_factor;
1203 const int size=0; //FIXME pass as arg
1205 const int ref_mv_stride= s->mb_stride;
1206 const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride;
1207 me_cmp_func cmpf, chroma_cmpf;
1209 int flags= c->flags;
1212 cmpf= s->dsp.me_cmp[size];
1213 chroma_cmpf= s->dsp.me_cmp[size+1];
1215 map_generation= update_map_generation(c);
1218 //printf("%d %d %d %d //",xmin, ymin, xmax, ymax);
1220 if (s->first_slice_line) {
1221 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1222 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1223 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1224 CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
1226 CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
1227 //FIXME try some early stop
1228 CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)
1229 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1230 CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift)
1231 CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
1232 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1233 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1236 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
1237 (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
1238 if(s->mb_y+1<s->end_mb_y) //FIXME replace at least with last_slice_line
1239 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
1240 (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
1243 dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
1248 // printf("%d %d %d \n", best[0], best[1], dmin);