summaryrefslogtreecommitdiff
path: root/libavcodec/motion_est_template.c (plain)
blob: 0c21bbfe1a4ab028a958c48723422f20076d1658
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
50static int hpel_motion_search(MpegEncContext * s,
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
62 LOAD_COMMON
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
155static int no_sub_motion_search(MpegEncContext * s,
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
165static 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
177 LOAD_COMMON
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
192int 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
207static int qpel_motion_search(MpegEncContext * s,
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
222 LOAD_COMMON
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)\
405if( (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);\
406if( (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);\
407if( (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);\
408if( (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
415static 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;
422 LOAD_COMMON
423 LOAD_COMMON2
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
456static 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;
463 LOAD_COMMON
464 LOAD_COMMON2
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
498static 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;
504 LOAD_COMMON
505 LOAD_COMMON2
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
532static 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;
538 LOAD_COMMON
539 LOAD_COMMON2
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
570static 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;
576 LOAD_COMMON
577 LOAD_COMMON2
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
617static 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;
623 LOAD_COMMON
624 LOAD_COMMON2
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
680static 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;
689 LOAD_COMMON
690 LOAD_COMMON2
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
770static 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;
777 LOAD_COMMON
778 LOAD_COMMON2
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
831static 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 */
859static 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
877 LOAD_COMMON
878 LOAD_COMMON2
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)) ||
899 s->mpv_flags & FF_MPV_FLAG_MV0)
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)
926 CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[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
976int 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
992static int epzs_motion_search4(MpegEncContext * s,
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
1027 CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)
1028 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1029 CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift)
1030 CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[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)
1051static int epzs_motion_search2(MpegEncContext * s,
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
1086 CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)
1087 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1088 CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift)
1089 CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[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}
1108