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