3 * Copyright (c) 2002-2004 Michael Niedermayer
5 * This file is part of Libav.
7 * Libav 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 * Libav 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 Libav; 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;
162 int map_generation= c->map_generation;
164 uint32_t *map= c->map;
166 key= ((my-1)<<ME_MAP_MV_BITS) + (mx) + map_generation;
167 assert(map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key);
168 key= ((my+1)<<ME_MAP_MV_BITS) + (mx) + map_generation;
169 assert(map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key);
170 key= ((my)<<ME_MAP_MV_BITS) + (mx+1) + map_generation;
171 assert(map[(index+1)&(ME_MAP_SIZE-1)] == key);
172 key= ((my)<<ME_MAP_MV_BITS) + (mx-1) + map_generation;
173 assert(map[(index-1)&(ME_MAP_SIZE-1)] == key);
175 CHECK_HALF_MV(0, 1, mx ,my-1)
177 CHECK_HALF_MV(1, 1, mx-1, my-1)
179 CHECK_HALF_MV(1, 1, mx , my-1)
181 CHECK_HALF_MV(1, 1, mx-1, my )
183 CHECK_HALF_MV(1, 0, mx-1, my )
185 CHECK_HALF_MV(1, 1, mx , my-1)
187 CHECK_HALF_MV(1, 1, mx-1, my-1)
189 CHECK_HALF_MV(1, 1, mx , my )
191 CHECK_HALF_MV(1, 0, mx , my )
196 CHECK_HALF_MV(1, 1, mx-1, my-1)
198 CHECK_HALF_MV(1, 1, mx , my )
200 CHECK_HALF_MV(1, 0, mx-1, my)
201 CHECK_HALF_MV(1, 1, mx-1, my)
204 CHECK_HALF_MV(1, 1, mx , my-1)
206 CHECK_HALF_MV(1, 1, mx-1, my)
208 CHECK_HALF_MV(1, 0, mx , my)
209 CHECK_HALF_MV(1, 1, mx , my)
211 CHECK_HALF_MV(0, 1, mx , my)
213 assert(bx >= xmin*2 && bx <= xmax*2 && by >= ymin*2 && by <= ymax*2);
223 static int no_sub_motion_search(MpegEncContext * s,
224 int *mx_ptr, int *my_ptr, int dmin,
225 int src_index, int ref_index,
233 inline int ff_get_mb_score(MpegEncContext * s, int mx, int my, int src_index,
234 int ref_index, int size, int h, int add_rate)
236 // const int check_luma= s->dsp.me_sub_cmp != s->dsp.mb_cmp;
237 MotionEstContext * const c= &s->me;
238 const int penalty_factor= c->mb_penalty_factor;
239 const int flags= c->mb_flags;
240 const int qpel= flags & FLAG_QPEL;
241 const int mask= 1+2*qpel;
242 me_cmp_func cmp_sub, chroma_cmp_sub;
249 cmp_sub= s->dsp.mb_cmp[size];
250 chroma_cmp_sub= s->dsp.mb_cmp[size+1];
253 // assert(c->avctx->me_sub_cmp != c->avctx->mb_cmp);
255 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);
256 //FIXME check cbp before adding penalty for (0,0) vector
257 if(add_rate && (mx || my || size>0))
258 d += (mv_penalty[mx - pred_x] + mv_penalty[my - pred_y])*penalty_factor;
263 #define CHECK_QUARTER_MV(dx, dy, x, y)\
265 const int hx= 4*(x)+(dx);\
266 const int hy= 4*(y)+(dy);\
267 d= cmp_qpel(s, x, y, dx, dy, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
268 d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\
269 COPY3_IF_LT(dmin, d, bx, hx, by, hy)\
272 static int qpel_motion_search(MpegEncContext * s,
273 int *mx_ptr, int *my_ptr, int dmin,
274 int src_index, int ref_index,
277 MotionEstContext * const c= &s->me;
278 const int mx = *mx_ptr;
279 const int my = *my_ptr;
280 const int penalty_factor= c->sub_penalty_factor;
281 const int map_generation= c->map_generation;
282 const int subpel_quality= c->avctx->me_subpel_quality;
283 uint32_t *map= c->map;
284 me_cmp_func cmpf, chroma_cmpf;
285 me_cmp_func cmp_sub, chroma_cmp_sub;
288 int flags= c->sub_flags;
290 cmpf= s->dsp.me_cmp[size];
291 chroma_cmpf= s->dsp.me_cmp[size+1]; //factorize FIXME
294 cmp_sub= s->dsp.me_sub_cmp[size];
295 chroma_cmp_sub= s->dsp.me_sub_cmp[size+1];
297 if(c->skip){ //FIXME somehow move up (benchmark)
303 if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
304 dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
305 if(mx || my || size>0)
306 dmin += (mv_penalty[4*mx - pred_x] + mv_penalty[4*my - pred_y])*penalty_factor;
309 if (mx > xmin && mx < xmax &&
310 my > ymin && my < ymax) {
311 int bx=4*mx, by=4*my;
314 const int index= (my<<ME_MAP_SHIFT) + mx;
315 const int t= score_map[(index-(1<<ME_MAP_SHIFT) )&(ME_MAP_SIZE-1)];
316 const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)];
317 const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)];
318 const int b= score_map[(index+(1<<ME_MAP_SHIFT) )&(ME_MAP_SIZE-1)];
319 const int c= score_map[(index )&(ME_MAP_SIZE-1)];
323 memset(best, 64, sizeof(int)*8);
325 if(s->me.dia_size>=2){
326 const int tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
327 const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
328 const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
329 const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
331 for(ny= -3; ny <= 3; ny++){
332 for(nx= -3; nx <= 3; nx++){
333 //FIXME this could overflow (unlikely though)
334 const int64_t t2= nx*nx*(tr + tl - 2*t) + 4*nx*(tr-tl) + 32*t;
335 const int64_t c2= nx*nx*( r + l - 2*c) + 4*nx*( r- l) + 32*c;
336 const int64_t b2= nx*nx*(br + bl - 2*b) + 4*nx*(br-bl) + 32*b;
337 int score= (ny*ny*(b2 + t2 - 2*c2) + 4*ny*(b2 - t2) + 32*c2 + 512)>>10;
340 if((nx&3)==0 && (ny&3)==0) continue;
342 score += (mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;
344 // if(nx&1) score-=1024*c->penalty_factor;
345 // if(ny&1) score-=1024*c->penalty_factor;
349 memmove(&best[i+1], &best[i], sizeof(int)*(7-i));
350 memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i));
352 best_pos[i][0]= nx + 4*mx;
353 best_pos[i][1]= ny + 4*my;
361 //FIXME this could overflow (unlikely though)
362 const int cx = 4*(r - l);
363 const int cx2= r + l - 2*c;
364 const int cy = 4*(b - t);
365 const int cy2= b + t - 2*c;
368 if(map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)] == (my<<ME_MAP_MV_BITS) + mx + map_generation && 0){ //FIXME
369 tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
371 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 cxy= 2*tl + (cx + cy)/4 - (cx2 + cy2) - 2*c;
376 assert(16*cx2 + 4*cx + 32*c == 32*r);
377 assert(16*cx2 - 4*cx + 32*c == 32*l);
378 assert(16*cy2 + 4*cy + 32*c == 32*b);
379 assert(16*cy2 - 4*cy + 32*c == 32*t);
380 assert(16*cxy + 16*cy2 + 16*cx2 - 4*cy - 4*cx + 32*c == 32*tl);
382 for(ny= -3; ny <= 3; ny++){
383 for(nx= -3; nx <= 3; nx++){
384 //FIXME this could overflow (unlikely though)
385 int score= ny*nx*cxy + nx*nx*cx2 + ny*ny*cy2 + nx*cx + ny*cy + 32*c; //FIXME factor
388 if((nx&3)==0 && (ny&3)==0) continue;
390 score += 32*(mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;
391 // if(nx&1) score-=32*c->penalty_factor;
392 // if(ny&1) score-=32*c->penalty_factor;
396 memmove(&best[i+1], &best[i], sizeof(int)*(7-i));
397 memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i));
399 best_pos[i][0]= nx + 4*mx;
400 best_pos[i][1]= ny + 4*my;
407 for(i=0; i<subpel_quality; i++){
410 CHECK_QUARTER_MV(nx&3, ny&3, nx>>2, ny>>2)
414 const int tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
415 const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
416 const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
417 const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
418 // if(l < r && l < t && l < b && l < tl && l < bl && l < tr && l < br && bl < tl){
421 // nx= FFMAX(4*mx - bx, bx - 4*mx);
422 // ny= FFMAX(4*my - by, by - 4*my);
424 static int stats[7][7], count;
426 stats[4*mx - bx + 3][4*my - by + 3]++;
427 if(256*256*256*64 % count ==0){
429 if((i%7)==0) printf("\n");
430 printf("%6d ", stats[0][i]);
438 CHECK_QUARTER_MV(2, 2, mx-1, my-1)
439 CHECK_QUARTER_MV(0, 2, mx , my-1)
440 CHECK_QUARTER_MV(2, 2, mx , my-1)
441 CHECK_QUARTER_MV(2, 0, mx , my )
442 CHECK_QUARTER_MV(2, 2, mx , my )
443 CHECK_QUARTER_MV(0, 2, mx , my )
444 CHECK_QUARTER_MV(2, 2, mx-1, my )
445 CHECK_QUARTER_MV(2, 0, mx-1, my )
451 int ox[8]= {0, 1, 1, 1, 0,-1,-1,-1};
452 int oy[8]= {1, 1, 0,-1,-1,-1, 0, 1};
453 CHECK_QUARTER_MV((nx + ox[i])&3, (ny + oy[i])&3, (nx + ox[i])>>2, (ny + oy[i])>>2)
458 CHECK_QUARTER_MV(1, 3, mx-1, my-1)
459 CHECK_QUARTER_MV(1, 2, mx-1, my-1)
460 CHECK_QUARTER_MV(1, 1, mx-1, my-1)
461 CHECK_QUARTER_MV(2, 1, mx-1, my-1)
462 CHECK_QUARTER_MV(3, 1, mx-1, my-1)
463 CHECK_QUARTER_MV(0, 1, mx , my-1)
464 CHECK_QUARTER_MV(1, 1, mx , my-1)
465 CHECK_QUARTER_MV(2, 1, mx , my-1)
466 CHECK_QUARTER_MV(3, 1, mx , my-1)
467 CHECK_QUARTER_MV(3, 2, mx , my-1)
468 CHECK_QUARTER_MV(3, 3, mx , my-1)
469 CHECK_QUARTER_MV(3, 0, mx , my )
470 CHECK_QUARTER_MV(3, 1, mx , my )
471 CHECK_QUARTER_MV(3, 2, mx , my )
472 CHECK_QUARTER_MV(3, 3, mx , my )
473 CHECK_QUARTER_MV(2, 3, mx , my )
474 CHECK_QUARTER_MV(1, 3, mx , my )
475 CHECK_QUARTER_MV(0, 3, mx , my )
476 CHECK_QUARTER_MV(3, 3, mx-1, my )
477 CHECK_QUARTER_MV(2, 3, mx-1, my )
478 CHECK_QUARTER_MV(1, 3, mx-1, my )
479 CHECK_QUARTER_MV(1, 2, mx-1, my )
480 CHECK_QUARTER_MV(1, 1, mx-1, my )
481 CHECK_QUARTER_MV(1, 0, mx-1, my )
483 assert(bx >= xmin*4 && bx <= xmax*4 && by >= ymin*4 && by <= ymax*4);
496 #define CHECK_MV(x,y)\
498 const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
499 const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
500 assert((x) >= xmin);\
501 assert((x) <= xmax);\
502 assert((y) >= ymin);\
503 assert((y) <= ymax);\
504 /*printf("check_mv %d %d\n", x, y);*/\
505 if(map[index]!=key){\
506 d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
508 score_map[index]= d;\
509 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\
510 /*printf("score:%d\n", d);*/\
511 COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\
515 #define CHECK_CLIPPED_MV(ax,ay)\
519 const int Lx2= FFMAX(xmin, FFMIN(Lx, xmax));\
520 const int Ly2= FFMAX(ymin, FFMIN(Ly, ymax));\
524 #define CHECK_MV_DIR(x,y,new_dir)\
526 const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
527 const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
528 /*printf("check_mv_dir %d %d %d\n", x, y, new_dir);*/\
529 if(map[index]!=key){\
530 d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
532 score_map[index]= d;\
533 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\
534 /*printf("score:%d\n", d);*/\
544 #define check(x,y,S,v)\
545 if( (x)<(xmin<<(S)) ) printf("%d %d %d %d %d xmin" #v, xmin, (x), (y), s->mb_x, s->mb_y);\
546 if( (x)>(xmax<<(S)) ) printf("%d %d %d %d %d xmax" #v, xmax, (x), (y), s->mb_x, s->mb_y);\
547 if( (y)<(ymin<<(S)) ) printf("%d %d %d %d %d ymin" #v, ymin, (x), (y), s->mb_x, s->mb_y);\
548 if( (y)>(ymax<<(S)) ) printf("%d %d %d %d %d ymax" #v, ymax, (x), (y), s->mb_x, s->mb_y);\
550 #define LOAD_COMMON2\
551 uint32_t *map= c->map;\
552 const int qpel= flags&FLAG_QPEL;\
553 const int shift= 1+qpel;\
555 static av_always_inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
556 int src_index, int ref_index, int const penalty_factor,
557 int size, int h, int flags)
559 MotionEstContext * const c= &s->me;
560 me_cmp_func cmpf, chroma_cmpf;
564 int map_generation= c->map_generation;
566 cmpf= s->dsp.me_cmp[size];
567 chroma_cmpf= s->dsp.me_cmp[size+1];
569 { /* ensure that the best point is in the MAP as h/qpel refinement needs it */
570 const int key= (best[1]<<ME_MAP_MV_BITS) + best[0] + map_generation;
571 const int index= ((best[1]<<ME_MAP_SHIFT) + best[0])&(ME_MAP_SIZE-1);
572 if(map[index]!=key){ //this will be executed only very rarey
573 score_map[index]= cmp(s, best[0], best[1], 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
580 const int dir= next_dir;
581 const int x= best[0];
582 const int y= best[1];
586 if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y , 0)
587 if(dir!=3 && y>ymin) CHECK_MV_DIR(x , y-1, 1)
588 if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y , 2)
589 if(dir!=1 && y<ymax) CHECK_MV_DIR(x , y+1, 3)
597 static int funny_diamond_search(MpegEncContext * s, int *best, int dmin,
598 int src_index, int ref_index, int const penalty_factor,
599 int size, int h, int flags)
601 MotionEstContext * const c= &s->me;
602 me_cmp_func cmpf, chroma_cmpf;
606 int map_generation= c->map_generation;
608 cmpf= s->dsp.me_cmp[size];
609 chroma_cmpf= s->dsp.me_cmp[size+1];
611 for(dia_size=1; dia_size<=4; dia_size++){
613 const int x= best[0];
614 const int y= best[1];
616 if(dia_size&(dia_size-1)) continue;
618 if( x + dia_size > xmax
619 || x - dia_size < xmin
620 || y + dia_size > ymax
621 || y - dia_size < ymin)
624 for(dir= 0; dir<dia_size; dir+=2){
627 CHECK_MV(x + dir , y + dia_size - dir);
628 CHECK_MV(x + dia_size - dir, y - dir );
629 CHECK_MV(x - dir , y - dia_size + dir);
630 CHECK_MV(x - dia_size + dir, y + dir );
633 if(x!=best[0] || y!=best[1])
639 static int hex_search(MpegEncContext * s, int *best, int dmin,
640 int src_index, int ref_index, int const penalty_factor,
641 int size, int h, int flags, int dia_size)
643 MotionEstContext * const c= &s->me;
644 me_cmp_func cmpf, chroma_cmpf;
647 int map_generation= c->map_generation;
649 const int dec= dia_size & (dia_size-1);
651 cmpf= s->dsp.me_cmp[size];
652 chroma_cmpf= s->dsp.me_cmp[size+1];
654 for(;dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){
659 CHECK_CLIPPED_MV(x -dia_size , y);
660 CHECK_CLIPPED_MV(x+ dia_size , y);
661 CHECK_CLIPPED_MV(x+( dia_size>>1), y+dia_size);
662 CHECK_CLIPPED_MV(x+( dia_size>>1), y-dia_size);
664 CHECK_CLIPPED_MV(x+(-dia_size>>1), y+dia_size);
665 CHECK_CLIPPED_MV(x+(-dia_size>>1), y-dia_size);
667 }while(best[0] != x || best[1] != y);
673 static int l2s_dia_search(MpegEncContext * s, int *best, int dmin,
674 int src_index, int ref_index, int const penalty_factor,
675 int size, int h, int flags)
677 MotionEstContext * const c= &s->me;
678 me_cmp_func cmpf, chroma_cmpf;
681 int map_generation= c->map_generation;
683 int dia_size= c->dia_size&0xFF;
684 const int dec= dia_size & (dia_size-1);
685 static const int hex[8][2]={{-2, 0}, {-1,-1}, { 0,-2}, { 1,-1},
686 { 2, 0}, { 1, 1}, { 0, 2}, {-1, 1}};
688 cmpf= s->dsp.me_cmp[size];
689 chroma_cmpf= s->dsp.me_cmp[size+1];
691 for(; dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){
696 CHECK_CLIPPED_MV(x+hex[i][0]*dia_size, y+hex[i][1]*dia_size);
698 }while(best[0] != x || best[1] != y);
703 CHECK_CLIPPED_MV(x+1, y);
704 CHECK_CLIPPED_MV(x, y+1);
705 CHECK_CLIPPED_MV(x-1, y);
706 CHECK_CLIPPED_MV(x, y-1);
711 static int umh_search(MpegEncContext * s, int *best, int dmin,
712 int src_index, int ref_index, int const penalty_factor,
713 int size, int h, int flags)
715 MotionEstContext * const c= &s->me;
716 me_cmp_func cmpf, chroma_cmpf;
719 int map_generation= c->map_generation;
720 int x,y,x2,y2, i, j, d;
721 const int dia_size= c->dia_size&0xFE;
722 static const int hex[16][2]={{-4,-2}, {-4,-1}, {-4, 0}, {-4, 1}, {-4, 2},
723 { 4,-2}, { 4,-1}, { 4, 0}, { 4, 1}, { 4, 2},
724 {-2, 3}, { 0, 4}, { 2, 3},
725 {-2,-3}, { 0,-4}, { 2,-3},};
727 cmpf= s->dsp.me_cmp[size];
728 chroma_cmpf= s->dsp.me_cmp[size+1];
732 for(x2=FFMAX(x-dia_size+1, xmin); x2<=FFMIN(x+dia_size-1,xmax); x2+=2){
735 for(y2=FFMAX(y-dia_size/2+1, ymin); y2<=FFMIN(y+dia_size/2-1,ymax); y2+=2){
741 for(y2=FFMAX(y-2, ymin); y2<=FFMIN(y+2,ymax); y2++){
742 for(x2=FFMAX(x-2, xmin); x2<=FFMIN(x+2,xmax); x2++){
747 //FIXME prevent the CLIP stuff
749 for(j=1; j<=dia_size/4; j++){
751 CHECK_CLIPPED_MV(x+hex[i][0]*j, y+hex[i][1]*j);
755 return hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, 2);
758 static int full_search(MpegEncContext * s, int *best, int dmin,
759 int src_index, int ref_index, int const penalty_factor,
760 int size, int h, int flags)
762 MotionEstContext * const c= &s->me;
763 me_cmp_func cmpf, chroma_cmpf;
766 int map_generation= c->map_generation;
768 const int dia_size= c->dia_size&0xFF;
770 cmpf= s->dsp.me_cmp[size];
771 chroma_cmpf= s->dsp.me_cmp[size+1];
773 for(y=FFMAX(-dia_size, ymin); y<=FFMIN(dia_size,ymax); y++){
774 for(x=FFMAX(-dia_size, xmin); x<=FFMIN(dia_size,xmax); x++){
782 CHECK_CLIPPED_MV(x , y);
783 CHECK_CLIPPED_MV(x+1, y);
784 CHECK_CLIPPED_MV(x, y+1);
785 CHECK_CLIPPED_MV(x-1, y);
786 CHECK_CLIPPED_MV(x, y-1);
793 #define SAB_CHECK_MV(ax,ay)\
795 const int key= ((ay)<<ME_MAP_MV_BITS) + (ax) + map_generation;\
796 const int index= (((ay)<<ME_MAP_SHIFT) + (ax))&(ME_MAP_SIZE-1);\
797 /*printf("sab check %d %d\n", ax, ay);*/\
798 if(map[index]!=key){\
799 d= cmp(s, ax, ay, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
801 score_map[index]= d;\
802 d += (mv_penalty[((ax)<<shift)-pred_x] + mv_penalty[((ay)<<shift)-pred_y])*penalty_factor;\
803 /*printf("score: %d\n", d);*/\
804 if(d < minima[minima_count-1].height){\
807 while(d >= minima[j].height) j++;\
809 memmove(&minima [j+1], &minima [j], (minima_count - j - 1)*sizeof(Minima));\
811 minima[j].checked= 0;\
812 minima[j].height= d;\
822 #define MAX_SAB_SIZE ME_MAP_SIZE
823 static int sab_diamond_search(MpegEncContext * s, int *best, int dmin,
824 int src_index, int ref_index, int const penalty_factor,
825 int size, int h, int flags)
827 MotionEstContext * const c= &s->me;
828 me_cmp_func cmpf, chroma_cmpf;
829 Minima minima[MAX_SAB_SIZE];
830 const int minima_count= FFABS(c->dia_size);
834 int map_generation= c->map_generation;
836 cmpf= s->dsp.me_cmp[size];
837 chroma_cmpf= s->dsp.me_cmp[size+1];
839 /*Note j<MAX_SAB_SIZE is needed if MAX_SAB_SIZE < ME_MAP_SIZE as j can
840 become larger due to MVs overflowing their ME_MAP_MV_BITS bits space in map
842 for(j=i=0; i<ME_MAP_SIZE && j<MAX_SAB_SIZE; i++){
843 uint32_t key= map[i];
845 key += (1<<(ME_MAP_MV_BITS-1)) + (1<<(2*ME_MAP_MV_BITS-1));
847 if((key&((-1)<<(2*ME_MAP_MV_BITS))) != map_generation) continue;
849 minima[j].height= score_map[i];
850 minima[j].x= key & ((1<<ME_MAP_MV_BITS)-1); key>>=ME_MAP_MV_BITS;
851 minima[j].y= key & ((1<<ME_MAP_MV_BITS)-1);
852 minima[j].x-= (1<<(ME_MAP_MV_BITS-1));
853 minima[j].y-= (1<<(ME_MAP_MV_BITS-1));
855 // all entries in map should be in range except if the mv overflows their ME_MAP_MV_BITS bits space
856 if( minima[j].x > xmax || minima[j].x < xmin
857 || minima[j].y > ymax || minima[j].y < ymin)
861 if(minima[j].x || minima[j].y)
862 minima[j].height+= (mv_penalty[((minima[j].x)<<shift)-pred_x] + mv_penalty[((minima[j].y)<<shift)-pred_y])*penalty_factor;
867 qsort(minima, j, sizeof(Minima), minima_cmp);
869 for(; j<minima_count; j++){
870 minima[j].height=256*256*256*64;
872 minima[j].x= minima[j].y=0;
875 for(i=0; i<minima_count; i++){
876 const int x= minima[i].x;
877 const int y= minima[i].y;
880 if(minima[i].checked) continue;
882 if( x >= xmax || x <= xmin
883 || y >= ymax || y <= ymin)
888 SAB_CHECK_MV(x , y-1)
889 SAB_CHECK_MV(x , y+1)
891 minima[i].checked= 1;
894 best[0]= minima[0].x;
895 best[1]= minima[0].y;
896 dmin= minima[0].height;
898 if( best[0] < xmax && best[0] > xmin
899 && best[1] < ymax && best[1] > ymin){
901 //ensure that the refernece samples for hpel refinement are in the map
902 CHECK_MV(best[0]-1, best[1])
903 CHECK_MV(best[0]+1, best[1])
904 CHECK_MV(best[0], best[1]-1)
905 CHECK_MV(best[0], best[1]+1)
910 static int var_diamond_search(MpegEncContext * s, int *best, int dmin,
911 int src_index, int ref_index, int const penalty_factor,
912 int size, int h, int flags)
914 MotionEstContext * const c= &s->me;
915 me_cmp_func cmpf, chroma_cmpf;
919 int map_generation= c->map_generation;
921 cmpf= s->dsp.me_cmp[size];
922 chroma_cmpf= s->dsp.me_cmp[size+1];
924 for(dia_size=1; dia_size<=c->dia_size; dia_size++){
926 const int x= best[0];
927 const int y= best[1];
929 start= FFMAX(0, y + dia_size - ymax);
930 end = FFMIN(dia_size, xmax - x + 1);
931 for(dir= start; dir<end; dir++){
934 //check(x + dir,y + dia_size - dir,0, a0)
935 CHECK_MV(x + dir , y + dia_size - dir);
938 start= FFMAX(0, x + dia_size - xmax);
939 end = FFMIN(dia_size, y - ymin + 1);
940 for(dir= start; dir<end; dir++){
943 //check(x + dia_size - dir, y - dir,0, a1)
944 CHECK_MV(x + dia_size - dir, y - dir );
947 start= FFMAX(0, -y + dia_size + ymin );
948 end = FFMIN(dia_size, x - xmin + 1);
949 for(dir= start; dir<end; dir++){
952 //check(x - dir,y - dia_size + dir,0, a2)
953 CHECK_MV(x - dir , y - dia_size + dir);
956 start= FFMAX(0, -x + dia_size + xmin );
957 end = FFMIN(dia_size, ymax - y + 1);
958 for(dir= start; dir<end; dir++){
961 //check(x - dia_size + dir, y + dir,0, a3)
962 CHECK_MV(x - dia_size + dir, y + dir );
965 if(x!=best[0] || y!=best[1])
971 static av_always_inline int diamond_search(MpegEncContext * s, int *best, int dmin,
972 int src_index, int ref_index, int const penalty_factor,
973 int size, int h, int flags){
974 MotionEstContext * const c= &s->me;
976 return funny_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
977 else if(c->dia_size<-1)
978 return sab_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
979 else if(c->dia_size<2)
980 return small_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
981 else if(c->dia_size>1024)
982 return full_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);
990 return var_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
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
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)
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[]. */
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;
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];
1025 penalty_factor= c->penalty_factor;
1026 cmpf= s->dsp.me_cmp[size];
1027 chroma_cmpf= s->dsp.me_cmp[size+1];
1030 map_generation= update_map_generation(c);
1033 dmin= cmp(s, 0, 0, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
1034 map[0]= map_generation;
1037 //FIXME precalc first term below?
1038 if((s->pict_type == AV_PICTURE_TYPE_B && !(c->flags & FLAG_DIRECT)) || s->flags&CODEC_FLAG_MV0)
1039 dmin += (mv_penalty[pred_x] + mv_penalty[pred_y])*penalty_factor;
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)
1047 if(dmin<((h*h*s->avctx->mv0_threshold)>>8)
1048 && ( P_LEFT[0] |P_LEFT[1]
1050 |P_TOPRIGHT[0]|P_TOPRIGHT[1])==0){
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)
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)
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)
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);
1091 for(mb_y=ystart; mb_y<yend; mb_y++){
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;
1098 if(mx>xmax || mx<xmin || my>ymax || my<ymin) continue;
1104 //check(best[0],best[1],0, b0)
1105 dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
1107 //check(best[0],best[1],0, b1)
1111 // printf("%d %d %d \n", best[0], best[1], dmin);
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)
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);
1125 // return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, FLAG_QPEL);
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);
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],
1136 MotionEstContext * const c= &s->me;
1140 const int penalty_factor= c->penalty_factor;
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;
1147 int flags= c->flags;
1150 cmpf= s->dsp.me_cmp[size];
1151 chroma_cmpf= s->dsp.me_cmp[size+1];
1153 map_generation= update_map_generation(c);
1156 //printf("%d %d %d %d //",xmin, ymin, xmax, ymax);
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)
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)
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)
1181 dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
1186 // printf("%d %d %d \n", best[0], best[1], dmin);
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],
1196 MotionEstContext * const c= &s->me;
1200 const int penalty_factor= c->penalty_factor;
1201 const int size=0; //FIXME pass as arg
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;
1207 int flags= c->flags;
1210 cmpf= s->dsp.me_cmp[size];
1211 chroma_cmpf= s->dsp.me_cmp[size+1];
1213 map_generation= update_map_generation(c);
1216 //printf("%d %d %d %d //",xmin, ymin, xmax, ymax);
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)
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)
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)
1241 dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
1246 // printf("%d %d %d \n", best[0], best[1], dmin);