FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
motion_est_template.c
Go to the documentation of this file.
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
24  * Motion estimation template.
25  */
26 
27 //Let us 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_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)\
45 }
46 
48  int *mx_ptr, int *my_ptr, int dmin,
49  int src_index, int ref_index,
50  int size, int h)
51 {
52  MotionEstContext * const c= &s->me;
53  const int mx = *mx_ptr;
54  const int my = *my_ptr;
55  const int penalty_factor= c->sub_penalty_factor;
56  me_cmp_func cmp_sub, chroma_cmp_sub;
57  int bx=2*mx, by=2*my;
58 
60  int flags= c->sub_flags;
61 
62  //FIXME factorize
63 
64  cmp_sub= s->dsp.me_sub_cmp[size];
65  chroma_cmp_sub= s->dsp.me_sub_cmp[size+1];
66 
67  if(c->skip){ //FIXME move out of hpel?
68  *mx_ptr = 0;
69  *my_ptr = 0;
70  return dmin;
71  }
72 
73  if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
74  dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
75  if(mx || my || size>0)
76  dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor;
77  }
78 
79  if (mx > xmin && mx < xmax &&
80  my > ymin && my < ymax) {
81  int d= dmin;
82  const int index= (my<<ME_MAP_SHIFT) + mx;
83  const int t= score_map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)]
84  + (mv_penalty[bx - pred_x] + mv_penalty[by-2 - pred_y])*c->penalty_factor;
85  const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)]
86  + (mv_penalty[bx-2 - pred_x] + mv_penalty[by - pred_y])*c->penalty_factor;
87  const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)]
88  + (mv_penalty[bx+2 - pred_x] + mv_penalty[by - pred_y])*c->penalty_factor;
89  const int b= score_map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)]
90  + (mv_penalty[bx - pred_x] + mv_penalty[by+2 - pred_y])*c->penalty_factor;
91 
92 #if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 1
93  unsigned key;
94  unsigned map_generation= c->map_generation;
95  key= ((my-1)<<ME_MAP_MV_BITS) + (mx) + map_generation;
96  av_assert2(c->map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key);
97  key= ((my+1)<<ME_MAP_MV_BITS) + (mx) + map_generation;
98  av_assert2(c->map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key);
99  key= ((my)<<ME_MAP_MV_BITS) + (mx+1) + map_generation;
100  av_assert2(c->map[(index+1)&(ME_MAP_SIZE-1)] == key);
101  key= ((my)<<ME_MAP_MV_BITS) + (mx-1) + map_generation;
102  av_assert2(c->map[(index-1)&(ME_MAP_SIZE-1)] == key);
103 #endif
104  if(t<=b){
105  CHECK_HALF_MV(0, 1, mx ,my-1)
106  if(l<=r){
107  CHECK_HALF_MV(1, 1, mx-1, my-1)
108  if(t+r<=b+l){
109  CHECK_HALF_MV(1, 1, mx , my-1)
110  }else{
111  CHECK_HALF_MV(1, 1, mx-1, my )
112  }
113  CHECK_HALF_MV(1, 0, mx-1, my )
114  }else{
115  CHECK_HALF_MV(1, 1, mx , my-1)
116  if(t+l<=b+r){
117  CHECK_HALF_MV(1, 1, mx-1, my-1)
118  }else{
119  CHECK_HALF_MV(1, 1, mx , my )
120  }
121  CHECK_HALF_MV(1, 0, mx , my )
122  }
123  }else{
124  if(l<=r){
125  if(t+l<=b+r){
126  CHECK_HALF_MV(1, 1, mx-1, my-1)
127  }else{
128  CHECK_HALF_MV(1, 1, mx , my )
129  }
130  CHECK_HALF_MV(1, 0, mx-1, my)
131  CHECK_HALF_MV(1, 1, mx-1, my)
132  }else{
133  if(t+r<=b+l){
134  CHECK_HALF_MV(1, 1, mx , my-1)
135  }else{
136  CHECK_HALF_MV(1, 1, mx-1, my)
137  }
138  CHECK_HALF_MV(1, 0, mx , my)
139  CHECK_HALF_MV(1, 1, mx , my)
140  }
141  CHECK_HALF_MV(0, 1, mx , my)
142  }
143  av_assert2(bx >= xmin*2 && bx <= xmax*2 && by >= ymin*2 && by <= ymax*2);
144  }
145 
146  *mx_ptr = bx;
147  *my_ptr = by;
148 
149  return dmin;
150 }
151 
153  int *mx_ptr, int *my_ptr, int dmin,
154  int src_index, int ref_index,
155  int size, int h)
156 {
157  (*mx_ptr)<<=1;
158  (*my_ptr)<<=1;
159  return dmin;
160 }
161 
162 static inline int get_mb_score(MpegEncContext *s, int mx, int my,
163  int src_index, int ref_index, int size,
164  int h, int add_rate)
165 {
166 // const int check_luma= s->dsp.me_sub_cmp != s->dsp.mb_cmp;
167  MotionEstContext * const c= &s->me;
168  const int penalty_factor= c->mb_penalty_factor;
169  const int flags= c->mb_flags;
170  const int qpel= flags & FLAG_QPEL;
171  const int mask= 1+2*qpel;
172  me_cmp_func cmp_sub, chroma_cmp_sub;
173  int d;
174 
176 
177  //FIXME factorize
178 
179  cmp_sub= s->dsp.mb_cmp[size];
180  chroma_cmp_sub= s->dsp.mb_cmp[size+1];
181 
182  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);
183  //FIXME check cbp before adding penalty for (0,0) vector
184  if(add_rate && (mx || my || size>0))
185  d += (mv_penalty[mx - pred_x] + mv_penalty[my - pred_y])*penalty_factor;
186 
187  return d;
188 }
189 
190 int ff_get_mb_score(MpegEncContext *s, int mx, int my, int src_index,
191  int ref_index, int size, int h, int add_rate)
192 {
193  return get_mb_score(s, mx, my, src_index, ref_index, size, h, add_rate);
194 }
195 
196 #define CHECK_QUARTER_MV(dx, dy, x, y)\
197 {\
198  const int hx= 4*(x)+(dx);\
199  const int hy= 4*(y)+(dy);\
200  d= cmp_qpel(s, x, y, dx, dy, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
201  d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\
202  COPY3_IF_LT(dmin, d, bx, hx, by, hy)\
203 }
204 
206  int *mx_ptr, int *my_ptr, int dmin,
207  int src_index, int ref_index,
208  int size, int h)
209 {
210  MotionEstContext * const c= &s->me;
211  const int mx = *mx_ptr;
212  const int my = *my_ptr;
213  const int penalty_factor= c->sub_penalty_factor;
214  const unsigned map_generation = c->map_generation;
215  const int subpel_quality= c->avctx->me_subpel_quality;
216  uint32_t *map= c->map;
217  me_cmp_func cmpf, chroma_cmpf;
218  me_cmp_func cmp_sub, chroma_cmp_sub;
219 
221  int flags= c->sub_flags;
222 
223  cmpf= s->dsp.me_cmp[size];
224  chroma_cmpf= s->dsp.me_cmp[size+1]; //factorize FIXME
225  //FIXME factorize
226 
227  cmp_sub= s->dsp.me_sub_cmp[size];
228  chroma_cmp_sub= s->dsp.me_sub_cmp[size+1];
229 
230  if(c->skip){ //FIXME somehow move up (benchmark)
231  *mx_ptr = 0;
232  *my_ptr = 0;
233  return dmin;
234  }
235 
236  if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
237  dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
238  if(mx || my || size>0)
239  dmin += (mv_penalty[4*mx - pred_x] + mv_penalty[4*my - pred_y])*penalty_factor;
240  }
241 
242  if (mx > xmin && mx < xmax &&
243  my > ymin && my < ymax) {
244  int bx=4*mx, by=4*my;
245  int d= dmin;
246  int i, nx, ny;
247  const int index= (my<<ME_MAP_SHIFT) + mx;
248  const int t= score_map[(index-(1<<ME_MAP_SHIFT) )&(ME_MAP_SIZE-1)];
249  const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)];
250  const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)];
251  const int b= score_map[(index+(1<<ME_MAP_SHIFT) )&(ME_MAP_SIZE-1)];
252  const int c= score_map[(index )&(ME_MAP_SIZE-1)];
253  int best[8];
254  int best_pos[8][2];
255 
256  memset(best, 64, sizeof(int)*8);
257  if(s->me.dia_size>=2){
258  const int tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
259  const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
260  const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
261  const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
262 
263  for(ny= -3; ny <= 3; ny++){
264  for(nx= -3; nx <= 3; nx++){
265  //FIXME this could overflow (unlikely though)
266  const int64_t t2= nx*nx*(tr + tl - 2*t) + 4*nx*(tr-tl) + 32*t;
267  const int64_t c2= nx*nx*( r + l - 2*c) + 4*nx*( r- l) + 32*c;
268  const int64_t b2= nx*nx*(br + bl - 2*b) + 4*nx*(br-bl) + 32*b;
269  int score= (ny*ny*(b2 + t2 - 2*c2) + 4*ny*(b2 - t2) + 32*c2 + 512)>>10;
270  int i;
271 
272  if((nx&3)==0 && (ny&3)==0) continue;
273 
274  score += (mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;
275 
276 // if(nx&1) score-=1024*c->penalty_factor;
277 // if(ny&1) score-=1024*c->penalty_factor;
278 
279  for(i=0; i<8; i++){
280  if(score < best[i]){
281  memmove(&best[i+1], &best[i], sizeof(int)*(7-i));
282  memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i));
283  best[i]= score;
284  best_pos[i][0]= nx + 4*mx;
285  best_pos[i][1]= ny + 4*my;
286  break;
287  }
288  }
289  }
290  }
291  }else{
292  int tl;
293  //FIXME this could overflow (unlikely though)
294  const int cx = 4*(r - l);
295  const int cx2= r + l - 2*c;
296  const int cy = 4*(b - t);
297  const int cy2= b + t - 2*c;
298  int cxy;
299 
300  if(map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)] == (my<<ME_MAP_MV_BITS) + mx + map_generation && 0){ //FIXME
301  tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
302  }else{
303  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
304  }
305 
306  cxy= 2*tl + (cx + cy)/4 - (cx2 + cy2) - 2*c;
307 
308  av_assert2(16*cx2 + 4*cx + 32*c == 32*r);
309  av_assert2(16*cx2 - 4*cx + 32*c == 32*l);
310  av_assert2(16*cy2 + 4*cy + 32*c == 32*b);
311  av_assert2(16*cy2 - 4*cy + 32*c == 32*t);
312  av_assert2(16*cxy + 16*cy2 + 16*cx2 - 4*cy - 4*cx + 32*c == 32*tl);
313 
314  for(ny= -3; ny <= 3; ny++){
315  for(nx= -3; nx <= 3; nx++){
316  //FIXME this could overflow (unlikely though)
317  int score= ny*nx*cxy + nx*nx*cx2 + ny*ny*cy2 + nx*cx + ny*cy + 32*c; //FIXME factor
318  int i;
319 
320  if((nx&3)==0 && (ny&3)==0) continue;
321 
322  score += 32*(mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;
323 // if(nx&1) score-=32*c->penalty_factor;
324  // if(ny&1) score-=32*c->penalty_factor;
325 
326  for(i=0; i<8; i++){
327  if(score < best[i]){
328  memmove(&best[i+1], &best[i], sizeof(int)*(7-i));
329  memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i));
330  best[i]= score;
331  best_pos[i][0]= nx + 4*mx;
332  best_pos[i][1]= ny + 4*my;
333  break;
334  }
335  }
336  }
337  }
338  }
339  for(i=0; i<subpel_quality; i++){
340  nx= best_pos[i][0];
341  ny= best_pos[i][1];
342  CHECK_QUARTER_MV(nx&3, ny&3, nx>>2, ny>>2)
343  }
344 
345  av_assert2(bx >= xmin*4 && bx <= xmax*4 && by >= ymin*4 && by <= ymax*4);
346 
347  *mx_ptr = bx;
348  *my_ptr = by;
349  }else{
350  *mx_ptr =4*mx;
351  *my_ptr =4*my;
352  }
353 
354  return dmin;
355 }
356 
357 
358 #define CHECK_MV(x,y)\
359 {\
360  const unsigned key = ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
361  const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
362  av_assert2((x) >= xmin);\
363  av_assert2((x) <= xmax);\
364  av_assert2((y) >= ymin);\
365  av_assert2((y) <= ymax);\
366  if(map[index]!=key){\
367  d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
368  map[index]= key;\
369  score_map[index]= d;\
370  d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\
371  COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\
372  }\
373 }
374 
375 #define CHECK_CLIPPED_MV(ax,ay)\
376 {\
377  const int Lx= ax;\
378  const int Ly= ay;\
379  const int Lx2= FFMAX(xmin, FFMIN(Lx, xmax));\
380  const int Ly2= FFMAX(ymin, FFMIN(Ly, ymax));\
381  CHECK_MV(Lx2, Ly2)\
382 }
383 
384 #define CHECK_MV_DIR(x,y,new_dir)\
385 {\
386  const unsigned key = ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
387  const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
388  if(map[index]!=key){\
389  d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
390  map[index]= key;\
391  score_map[index]= d;\
392  d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\
393  if(d<dmin){\
394  best[0]=x;\
395  best[1]=y;\
396  dmin=d;\
397  next_dir= new_dir;\
398  }\
399  }\
400 }
401 
402 #define check(x,y,S,v)\
403 if( (x)<(xmin<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d xmin" #v, xmin, (x), (y), s->mb_x, s->mb_y);\
404 if( (x)>(xmax<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d xmax" #v, xmax, (x), (y), s->mb_x, s->mb_y);\
405 if( (y)<(ymin<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d ymin" #v, ymin, (x), (y), s->mb_x, s->mb_y);\
406 if( (y)>(ymax<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d ymax" #v, ymax, (x), (y), s->mb_x, s->mb_y);\
407 
408 #define LOAD_COMMON2\
409  uint32_t *map= c->map;\
410  const int qpel= flags&FLAG_QPEL;\
411  const int shift= 1+qpel;\
412 
413 static av_always_inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
414  int src_index, int ref_index, int const penalty_factor,
415  int size, int h, int flags)
416 {
417  MotionEstContext * const c= &s->me;
418  me_cmp_func cmpf, chroma_cmpf;
419  int next_dir=-1;
422  unsigned map_generation = c->map_generation;
423 
424  cmpf= s->dsp.me_cmp[size];
425  chroma_cmpf= s->dsp.me_cmp[size+1];
426 
427  { /* ensure that the best point is in the MAP as h/qpel refinement needs it */
428  const unsigned key = (best[1]<<ME_MAP_MV_BITS) + best[0] + map_generation;
429  const int index= ((best[1]<<ME_MAP_SHIFT) + best[0])&(ME_MAP_SIZE-1);
430  if(map[index]!=key){ //this will be executed only very rarey
431  score_map[index]= cmp(s, best[0], best[1], 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
432  map[index]= key;
433  }
434  }
435 
436  for(;;){
437  int d;
438  const int dir= next_dir;
439  const int x= best[0];
440  const int y= best[1];
441  next_dir=-1;
442 
443  if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y , 0)
444  if(dir!=3 && y>ymin) CHECK_MV_DIR(x , y-1, 1)
445  if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y , 2)
446  if(dir!=1 && y<ymax) CHECK_MV_DIR(x , y+1, 3)
447 
448  if(next_dir==-1){
449  return dmin;
450  }
451  }
452 }
453 
454 static int funny_diamond_search(MpegEncContext * s, int *best, int dmin,
455  int src_index, int ref_index, int const penalty_factor,
456  int size, int h, int flags)
457 {
458  MotionEstContext * const c= &s->me;
459  me_cmp_func cmpf, chroma_cmpf;
460  int dia_size;
463  unsigned map_generation = c->map_generation;
464 
465  cmpf= s->dsp.me_cmp[size];
466  chroma_cmpf= s->dsp.me_cmp[size+1];
467 
468  for(dia_size=1; dia_size<=4; dia_size++){
469  int dir;
470  const int x= best[0];
471  const int y= best[1];
472 
473  if(dia_size&(dia_size-1)) continue;
474 
475  if( x + dia_size > xmax
476  || x - dia_size < xmin
477  || y + dia_size > ymax
478  || y - dia_size < ymin)
479  continue;
480 
481  for(dir= 0; dir<dia_size; dir+=2){
482  int d;
483 
484  CHECK_MV(x + dir , y + dia_size - dir);
485  CHECK_MV(x + dia_size - dir, y - dir );
486  CHECK_MV(x - dir , y - dia_size + dir);
487  CHECK_MV(x - dia_size + dir, y + dir );
488  }
489 
490  if(x!=best[0] || y!=best[1])
491  dia_size=0;
492  }
493  return dmin;
494 }
495 
496 static int hex_search(MpegEncContext * s, int *best, int dmin,
497  int src_index, int ref_index, int const penalty_factor,
498  int size, int h, int flags, int dia_size)
499 {
500  MotionEstContext * const c= &s->me;
501  me_cmp_func cmpf, chroma_cmpf;
504  unsigned map_generation = c->map_generation;
505  int x,y,d;
506  const int dec= dia_size & (dia_size-1);
507 
508  cmpf= s->dsp.me_cmp[size];
509  chroma_cmpf= s->dsp.me_cmp[size+1];
510 
511  for(;dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){
512  do{
513  x= best[0];
514  y= best[1];
515 
516  CHECK_CLIPPED_MV(x -dia_size , y);
517  CHECK_CLIPPED_MV(x+ dia_size , y);
518  CHECK_CLIPPED_MV(x+( dia_size>>1), y+dia_size);
519  CHECK_CLIPPED_MV(x+( dia_size>>1), y-dia_size);
520  if(dia_size>1){
521  CHECK_CLIPPED_MV(x+(-dia_size>>1), y+dia_size);
522  CHECK_CLIPPED_MV(x+(-dia_size>>1), y-dia_size);
523  }
524  }while(best[0] != x || best[1] != y);
525  }
526 
527  return dmin;
528 }
529 
530 static int l2s_dia_search(MpegEncContext * s, int *best, int dmin,
531  int src_index, int ref_index, int const penalty_factor,
532  int size, int h, int flags)
533 {
534  MotionEstContext * const c= &s->me;
535  me_cmp_func cmpf, chroma_cmpf;
538  unsigned map_generation = c->map_generation;
539  int x,y,i,d;
540  int dia_size= c->dia_size&0xFF;
541  const int dec= dia_size & (dia_size-1);
542  static const int hex[8][2]={{-2, 0}, {-1,-1}, { 0,-2}, { 1,-1},
543  { 2, 0}, { 1, 1}, { 0, 2}, {-1, 1}};
544 
545  cmpf= s->dsp.me_cmp[size];
546  chroma_cmpf= s->dsp.me_cmp[size+1];
547 
548  for(; dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){
549  do{
550  x= best[0];
551  y= best[1];
552  for(i=0; i<8; i++){
553  CHECK_CLIPPED_MV(x+hex[i][0]*dia_size, y+hex[i][1]*dia_size);
554  }
555  }while(best[0] != x || best[1] != y);
556  }
557 
558  x= best[0];
559  y= best[1];
560  CHECK_CLIPPED_MV(x+1, y);
561  CHECK_CLIPPED_MV(x, y+1);
562  CHECK_CLIPPED_MV(x-1, y);
563  CHECK_CLIPPED_MV(x, y-1);
564 
565  return dmin;
566 }
567 
568 static int umh_search(MpegEncContext * s, int *best, int dmin,
569  int src_index, int ref_index, int const penalty_factor,
570  int size, int h, int flags)
571 {
572  MotionEstContext * const c= &s->me;
573  me_cmp_func cmpf, chroma_cmpf;
576  unsigned map_generation = c->map_generation;
577  int x,y,x2,y2, i, j, d;
578  const int dia_size= c->dia_size&0xFE;
579  static const int hex[16][2]={{-4,-2}, {-4,-1}, {-4, 0}, {-4, 1}, {-4, 2},
580  { 4,-2}, { 4,-1}, { 4, 0}, { 4, 1}, { 4, 2},
581  {-2, 3}, { 0, 4}, { 2, 3},
582  {-2,-3}, { 0,-4}, { 2,-3},};
583 
584  cmpf= s->dsp.me_cmp[size];
585  chroma_cmpf= s->dsp.me_cmp[size+1];
586 
587  x= best[0];
588  y= best[1];
589  for(x2=FFMAX(x-dia_size+1, xmin); x2<=FFMIN(x+dia_size-1,xmax); x2+=2){
590  CHECK_MV(x2, y);
591  }
592  for(y2=FFMAX(y-dia_size/2+1, ymin); y2<=FFMIN(y+dia_size/2-1,ymax); y2+=2){
593  CHECK_MV(x, y2);
594  }
595 
596  x= best[0];
597  y= best[1];
598  for(y2=FFMAX(y-2, ymin); y2<=FFMIN(y+2,ymax); y2++){
599  for(x2=FFMAX(x-2, xmin); x2<=FFMIN(x+2,xmax); x2++){
600  CHECK_MV(x2, y2);
601  }
602  }
603 
604 //FIXME prevent the CLIP stuff
605 
606  for(j=1; j<=dia_size/4; j++){
607  for(i=0; i<16; i++){
608  CHECK_CLIPPED_MV(x+hex[i][0]*j, y+hex[i][1]*j);
609  }
610  }
611 
612  return hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, 2);
613 }
614 
615 static int full_search(MpegEncContext * s, int *best, int dmin,
616  int src_index, int ref_index, int const penalty_factor,
617  int size, int h, int flags)
618 {
619  MotionEstContext * const c= &s->me;
620  me_cmp_func cmpf, chroma_cmpf;
623  unsigned map_generation = c->map_generation;
624  int x,y, d;
625  const int dia_size= c->dia_size&0xFF;
626 
627  cmpf= s->dsp.me_cmp[size];
628  chroma_cmpf= s->dsp.me_cmp[size+1];
629 
630  for(y=FFMAX(-dia_size, ymin); y<=FFMIN(dia_size,ymax); y++){
631  for(x=FFMAX(-dia_size, xmin); x<=FFMIN(dia_size,xmax); x++){
632  CHECK_MV(x, y);
633  }
634  }
635 
636  x= best[0];
637  y= best[1];
638  d= dmin;
639  CHECK_CLIPPED_MV(x , y);
640  CHECK_CLIPPED_MV(x+1, y);
641  CHECK_CLIPPED_MV(x, y+1);
642  CHECK_CLIPPED_MV(x-1, y);
643  CHECK_CLIPPED_MV(x, y-1);
644  best[0]= x;
645  best[1]= y;
646 
647  return d;
648 }
649 
650 #define SAB_CHECK_MV(ax,ay)\
651 {\
652  const unsigned key = ((ay)<<ME_MAP_MV_BITS) + (ax) + map_generation;\
653  const int index= (((ay)<<ME_MAP_SHIFT) + (ax))&(ME_MAP_SIZE-1);\
654  if(map[index]!=key){\
655  d= cmp(s, ax, ay, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
656  map[index]= key;\
657  score_map[index]= d;\
658  d += (mv_penalty[((ax)<<shift)-pred_x] + mv_penalty[((ay)<<shift)-pred_y])*penalty_factor;\
659  if(d < minima[minima_count-1].height){\
660  int j=0;\
661  \
662  while(d >= minima[j].height) j++;\
663 \
664  memmove(&minima [j+1], &minima [j], (minima_count - j - 1)*sizeof(Minima));\
665 \
666  minima[j].checked= 0;\
667  minima[j].height= d;\
668  minima[j].x= ax;\
669  minima[j].y= ay;\
670  \
671  i=-1;\
672  continue;\
673  }\
674  }\
675 }
676 
677 #define MAX_SAB_SIZE ME_MAP_SIZE
678 static int sab_diamond_search(MpegEncContext * s, int *best, int dmin,
679  int src_index, int ref_index, int const penalty_factor,
680  int size, int h, int flags)
681 {
682  MotionEstContext * const c= &s->me;
683  me_cmp_func cmpf, chroma_cmpf;
684  Minima minima[MAX_SAB_SIZE];
685  const int minima_count= FFABS(c->dia_size);
686  int i, j;
689  unsigned map_generation = c->map_generation;
690 
691  av_assert1(minima_count <= MAX_SAB_SIZE);
692 
693  cmpf= s->dsp.me_cmp[size];
694  chroma_cmpf= s->dsp.me_cmp[size+1];
695 
696  /*Note j<MAX_SAB_SIZE is needed if MAX_SAB_SIZE < ME_MAP_SIZE as j can
697  become larger due to MVs overflowing their ME_MAP_MV_BITS bits space in map
698  */
699  for(j=i=0; i<ME_MAP_SIZE && j<MAX_SAB_SIZE; i++){
700  uint32_t key= map[i];
701 
702  key += (1<<(ME_MAP_MV_BITS-1)) + (1<<(2*ME_MAP_MV_BITS-1));
703 
704  if((key&((-1)<<(2*ME_MAP_MV_BITS))) != map_generation) continue;
705 
706  minima[j].height= score_map[i];
707  minima[j].x= key & ((1<<ME_MAP_MV_BITS)-1); key>>=ME_MAP_MV_BITS;
708  minima[j].y= key & ((1<<ME_MAP_MV_BITS)-1);
709  minima[j].x-= (1<<(ME_MAP_MV_BITS-1));
710  minima[j].y-= (1<<(ME_MAP_MV_BITS-1));
711 
712  // all entries in map should be in range except if the mv overflows their ME_MAP_MV_BITS bits space
713  if( minima[j].x > xmax || minima[j].x < xmin
714  || minima[j].y > ymax || minima[j].y < ymin)
715  continue;
716 
717  minima[j].checked=0;
718  if(minima[j].x || minima[j].y)
719  minima[j].height+= (mv_penalty[((minima[j].x)<<shift)-pred_x] + mv_penalty[((minima[j].y)<<shift)-pred_y])*penalty_factor;
720 
721  j++;
722  }
723 
724  qsort(minima, j, sizeof(Minima), minima_cmp);
725 
726  for(; j<minima_count; j++){
727  minima[j].height=256*256*256*64;
728  minima[j].checked=0;
729  minima[j].x= minima[j].y=0;
730  }
731 
732  for(i=0; i<minima_count; i++){
733  const int x= minima[i].x;
734  const int y= minima[i].y;
735  int d;
736 
737  if(minima[i].checked) continue;
738 
739  if( x >= xmax || x <= xmin
740  || y >= ymax || y <= ymin)
741  continue;
742 
743  SAB_CHECK_MV(x-1, y)
744  SAB_CHECK_MV(x+1, y)
745  SAB_CHECK_MV(x , y-1)
746  SAB_CHECK_MV(x , y+1)
747 
748  minima[i].checked= 1;
749  }
750 
751  best[0]= minima[0].x;
752  best[1]= minima[0].y;
753  dmin= minima[0].height;
754 
755  if( best[0] < xmax && best[0] > xmin
756  && best[1] < ymax && best[1] > ymin){
757  int d;
758  //ensure that the refernece samples for hpel refinement are in the map
759  CHECK_MV(best[0]-1, best[1])
760  CHECK_MV(best[0]+1, best[1])
761  CHECK_MV(best[0], best[1]-1)
762  CHECK_MV(best[0], best[1]+1)
763  }
764  return dmin;
765 }
766 
767 static int var_diamond_search(MpegEncContext * s, int *best, int dmin,
768  int src_index, int ref_index, int const penalty_factor,
769  int size, int h, int flags)
770 {
771  MotionEstContext * const c= &s->me;
772  me_cmp_func cmpf, chroma_cmpf;
773  int dia_size;
776  unsigned map_generation = c->map_generation;
777 
778  cmpf= s->dsp.me_cmp[size];
779  chroma_cmpf= s->dsp.me_cmp[size+1];
780 
781  for(dia_size=1; dia_size<=c->dia_size; dia_size++){
782  int dir, start, end;
783  const int x= best[0];
784  const int y= best[1];
785 
786  start= FFMAX(0, y + dia_size - ymax);
787  end = FFMIN(dia_size, xmax - x + 1);
788  for(dir= start; dir<end; dir++){
789  int d;
790 
791 //check(x + dir,y + dia_size - dir,0, a0)
792  CHECK_MV(x + dir , y + dia_size - dir);
793  }
794 
795  start= FFMAX(0, x + dia_size - xmax);
796  end = FFMIN(dia_size, y - ymin + 1);
797  for(dir= start; dir<end; dir++){
798  int d;
799 
800 //check(x + dia_size - dir, y - dir,0, a1)
801  CHECK_MV(x + dia_size - dir, y - dir );
802  }
803 
804  start= FFMAX(0, -y + dia_size + ymin );
805  end = FFMIN(dia_size, x - xmin + 1);
806  for(dir= start; dir<end; dir++){
807  int d;
808 
809 //check(x - dir,y - dia_size + dir,0, a2)
810  CHECK_MV(x - dir , y - dia_size + dir);
811  }
812 
813  start= FFMAX(0, -x + dia_size + xmin );
814  end = FFMIN(dia_size, ymax - y + 1);
815  for(dir= start; dir<end; dir++){
816  int d;
817 
818 //check(x - dia_size + dir, y + dir,0, a3)
819  CHECK_MV(x - dia_size + dir, y + dir );
820  }
821 
822  if(x!=best[0] || y!=best[1])
823  dia_size=0;
824  }
825  return dmin;
826 }
827 
828 static av_always_inline int diamond_search(MpegEncContext * s, int *best, int dmin,
829  int src_index, int ref_index, int const penalty_factor,
830  int size, int h, int flags){
831  MotionEstContext * const c= &s->me;
832  if(c->dia_size==-1)
833  return funny_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
834  else if(c->dia_size<-1)
835  return sab_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
836  else if(c->dia_size<2)
837  return small_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
838  else if(c->dia_size>1024)
839  return full_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
840  else if(c->dia_size>768)
841  return umh_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
842  else if(c->dia_size>512)
843  return hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, c->dia_size&0xFF);
844  else if(c->dia_size>256)
845  return l2s_dia_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
846  else
847  return var_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
848 }
849 
850 /**
851  @param P a list of candidate mvs to check before starting the
852  iterative search. If one of the candidates is close to the optimal mv, then
853  it takes fewer iterations. And it increases the chance that we find the
854  optimal mv.
855  */
856 static av_always_inline int epzs_motion_search_internal(MpegEncContext * s, int *mx_ptr, int *my_ptr,
857  int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2],
858  int ref_mv_scale, int flags, int size, int h)
859 {
860  MotionEstContext * const c= &s->me;
861  int best[2]={0, 0}; /**< x and y coordinates of the best motion vector.
862  i.e. the difference between the position of the
863  block currently being encoded and the position of
864  the block chosen to predict it from. */
865  int d; ///< the score (cmp + penalty) of any given mv
866  int dmin; /**< the best value of d, i.e. the score
867  corresponding to the mv stored in best[]. */
868  unsigned map_generation;
869  int penalty_factor;
870  const int ref_mv_stride= s->mb_stride; //pass as arg FIXME
871  const int ref_mv_xy= s->mb_x + s->mb_y*ref_mv_stride; //add to last_mv beforepassing FIXME
872  me_cmp_func cmpf, chroma_cmpf;
873 
876 
877  if(c->pre_pass){
878  penalty_factor= c->pre_penalty_factor;
879  cmpf= s->dsp.me_pre_cmp[size];
880  chroma_cmpf= s->dsp.me_pre_cmp[size+1];
881  }else{
882  penalty_factor= c->penalty_factor;
883  cmpf= s->dsp.me_cmp[size];
884  chroma_cmpf= s->dsp.me_cmp[size+1];
885  }
886 
887  map_generation= update_map_generation(c);
888 
889  av_assert2(cmpf);
890  dmin= cmp(s, 0, 0, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
891  map[0]= map_generation;
892  score_map[0]= dmin;
893 
894  //FIXME precalc first term below?
895  if((s->pict_type == AV_PICTURE_TYPE_B && !(c->flags & FLAG_DIRECT)) || s->flags&CODEC_FLAG_MV0)
896  dmin += (mv_penalty[pred_x] + mv_penalty[pred_y])*penalty_factor;
897 
898  /* first line */
899  if (s->first_slice_line) {
900  CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
901  CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
902  (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
903  }else{
904  if(dmin<((h*h*s->avctx->mv0_threshold)>>8)
905  && ( P_LEFT[0] |P_LEFT[1]
906  |P_TOP[0] |P_TOP[1]
907  |P_TOPRIGHT[0]|P_TOPRIGHT[1])==0){
908  *mx_ptr= 0;
909  *my_ptr= 0;
910  c->skip=1;
911  return dmin;
912  }
913  CHECK_MV( P_MEDIAN[0] >>shift , P_MEDIAN[1] >>shift)
914  CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift) , (P_MEDIAN[1]>>shift)-1)
915  CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift) , (P_MEDIAN[1]>>shift)+1)
916  CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)-1, (P_MEDIAN[1]>>shift) )
917  CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)+1, (P_MEDIAN[1]>>shift) )
918  CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
919  (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
920  CHECK_MV(P_LEFT[0] >>shift, P_LEFT[1] >>shift)
921  CHECK_MV(P_TOP[0] >>shift, P_TOP[1] >>shift)
923  }
924  if(dmin>h*h*4){
925  if(c->pre_pass){
926  CHECK_CLIPPED_MV((last_mv[ref_mv_xy-1][0]*ref_mv_scale + (1<<15))>>16,
927  (last_mv[ref_mv_xy-1][1]*ref_mv_scale + (1<<15))>>16)
928  if(!s->first_slice_line)
929  CHECK_CLIPPED_MV((last_mv[ref_mv_xy-ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
930  (last_mv[ref_mv_xy-ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
931  }else{
932  CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
933  (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
934  if(s->mb_y+1<s->end_mb_y) //FIXME replace at least with last_slice_line
935  CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
936  (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
937  }
938  }
939 
940  if(c->avctx->last_predictor_count){
941  const int count= c->avctx->last_predictor_count;
942  const int xstart= FFMAX(0, s->mb_x - count);
943  const int ystart= FFMAX(0, s->mb_y - count);
944  const int xend= FFMIN(s->mb_width , s->mb_x + count + 1);
945  const int yend= FFMIN(s->mb_height, s->mb_y + count + 1);
946  int mb_y;
947 
948  for(mb_y=ystart; mb_y<yend; mb_y++){
949  int mb_x;
950  for(mb_x=xstart; mb_x<xend; mb_x++){
951  const int xy= mb_x + 1 + (mb_y + 1)*ref_mv_stride;
952  int mx= (last_mv[xy][0]*ref_mv_scale + (1<<15))>>16;
953  int my= (last_mv[xy][1]*ref_mv_scale + (1<<15))>>16;
954 
955  if(mx>xmax || mx<xmin || my>ymax || my<ymin) continue;
956  CHECK_MV(mx,my)
957  }
958  }
959  }
960 
961 //check(best[0],best[1],0, b0)
962  dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
963 
964 //check(best[0],best[1],0, b1)
965  *mx_ptr= best[0];
966  *my_ptr= best[1];
967 
968  return dmin;
969 }
970 
971 //this function is dedicated to the braindamaged gcc
972 int ff_epzs_motion_search(MpegEncContext *s, int *mx_ptr, int *my_ptr,
973  int P[10][2], int src_index, int ref_index,
974  int16_t (*last_mv)[2], int ref_mv_scale,
975  int size, int h)
976 {
977  MotionEstContext * const c= &s->me;
978 //FIXME convert other functions in the same way if faster
979  if(c->flags==0 && h==16 && size==0){
980  return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, 0, 0, 16);
981 // case FLAG_QPEL:
982 // return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, FLAG_QPEL);
983  }else{
984  return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, c->flags, size, h);
985  }
986 }
987 
989  int *mx_ptr, int *my_ptr, int P[10][2],
990  int src_index, int ref_index, int16_t (*last_mv)[2],
991  int ref_mv_scale)
992 {
993  MotionEstContext * const c= &s->me;
994  int best[2]={0, 0};
995  int d, dmin;
996  unsigned map_generation;
997  const int penalty_factor= c->penalty_factor;
998  const int size=1;
999  const int h=8;
1000  const int ref_mv_stride= s->mb_stride;
1001  const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride;
1002  me_cmp_func cmpf, chroma_cmpf;
1003  LOAD_COMMON
1004  int flags= c->flags;
1005  LOAD_COMMON2
1006 
1007  cmpf= s->dsp.me_cmp[size];
1008  chroma_cmpf= s->dsp.me_cmp[size+1];
1009 
1010  map_generation= update_map_generation(c);
1011 
1012  dmin = 1000000;
1013 
1014  /* first line */
1015  if (s->first_slice_line) {
1016  CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1017  CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1018  (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1019  CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
1020  }else{
1021  CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
1022  //FIXME try some early stop
1024  CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1025  CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift)
1027  CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1028  (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1029  }
1030  if(dmin>64*4){
1031  CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
1032  (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
1033  if(s->mb_y+1<s->end_mb_y) //FIXME replace at least with last_slice_line
1034  CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
1035  (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
1036  }
1037 
1038  dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
1039 
1040  *mx_ptr= best[0];
1041  *my_ptr= best[1];
1042 
1043  return dmin;
1044 }
1045 
1046 //try to merge with above FIXME (needs PSNR test)
1048  int *mx_ptr, int *my_ptr, int P[10][2],
1049  int src_index, int ref_index, int16_t (*last_mv)[2],
1050  int ref_mv_scale)
1051 {
1052  MotionEstContext * const c= &s->me;
1053  int best[2]={0, 0};
1054  int d, dmin;
1055  unsigned map_generation;
1056  const int penalty_factor= c->penalty_factor;
1057  const int size=0; //FIXME pass as arg
1058  const int h=8;
1059  const int ref_mv_stride= s->mb_stride;
1060  const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride;
1061  me_cmp_func cmpf, chroma_cmpf;
1062  LOAD_COMMON
1063  int flags= c->flags;
1064  LOAD_COMMON2
1065 
1066  cmpf= s->dsp.me_cmp[size];
1067  chroma_cmpf= s->dsp.me_cmp[size+1];
1068 
1069  map_generation= update_map_generation(c);
1070 
1071  dmin = 1000000;
1072 
1073  /* first line */
1074  if (s->first_slice_line) {
1075  CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1076  CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1077  (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1078  CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
1079  }else{
1080  CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
1081  //FIXME try some early stop
1083  CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1084  CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift)
1086  CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1087  (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1088  }
1089  if(dmin>64*4){
1090  CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
1091  (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
1092  if(s->mb_y+1<s->end_mb_y) //FIXME replace at least with last_slice_line
1093  CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
1094  (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
1095  }
1096 
1097  dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
1098 
1099  *mx_ptr= best[0];
1100  *my_ptr= best[1];
1101 
1102  return dmin;
1103 }