FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/motion_est_template.c
Date: 2026-10-06 20:08:58
Exec Total Coverage
Lines: 311 498 62.4%
Functions: 11 17 64.7%
Branches: 228 490 46.5%

Line Branch Exec Source
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 "mpegvideoenc.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 av_unused uint32_t * const score_map= c->score_map;\
33 av_unused const int xmin= c->xmin;\
34 av_unused const int ymin= c->ymin;\
35 av_unused const int xmax= c->xmax;\
36 av_unused const int ymax= c->ymax;\
37 const 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
50 701135 static int hpel_motion_search(MPVEncContext *const s,
51 int *mx_ptr, int *my_ptr, int dmin,
52 int src_index, int ref_index,
53 int size, int h)
54 {
55 701135 MotionEstContext *const c = &s->me;
56 701135 const int mx = *mx_ptr;
57 701135 const int my = *my_ptr;
58 701135 const int penalty_factor= c->sub_penalty_factor;
59 me_cmp_func cmp_sub, chroma_cmp_sub;
60 701135 int bx=2*mx, by=2*my;
61
62 701135 LOAD_COMMON
63 701135 int flags= c->sub_flags;
64
65 //FIXME factorize
66
67 701135 cmp_sub = c->me_sub_cmp[size];
68 701135 chroma_cmp_sub = c->me_sub_cmp[size + 1];
69
70
2/2
✓ Branch 0 taken 771 times.
✓ Branch 1 taken 700364 times.
701135 if(c->skip){ //FIXME move out of hpel?
71 771 *mx_ptr = 0;
72 771 *my_ptr = 0;
73 771 return dmin;
74 }
75
76
2/2
✓ Branch 0 taken 289800 times.
✓ Branch 1 taken 410564 times.
700364 if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
77 289800 dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
78
6/6
✓ Branch 0 taken 49310 times.
✓ Branch 1 taken 240490 times.
✓ Branch 2 taken 23929 times.
✓ Branch 3 taken 25381 times.
✓ Branch 4 taken 1889 times.
✓ Branch 5 taken 22040 times.
289800 if(mx || my || size>0)
79 267760 dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor;
80 }
81
82
6/6
✓ Branch 0 taken 696170 times.
✓ Branch 1 taken 4194 times.
✓ Branch 2 taken 692808 times.
✓ Branch 3 taken 3362 times.
✓ Branch 4 taken 689747 times.
✓ Branch 5 taken 3061 times.
700364 if (mx > xmin && mx < xmax &&
83
2/2
✓ Branch 0 taken 686486 times.
✓ Branch 1 taken 3261 times.
689747 my > ymin && my < ymax) {
84 686486 int d= dmin;
85 686486 const int index = my * (1 << ME_MAP_SHIFT) + mx;
86 686486 const int t= score_map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)]
87 686486 + (mv_penalty[bx - pred_x] + mv_penalty[by-2 - pred_y])*c->penalty_factor;
88 686486 const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)]
89 686486 + (mv_penalty[bx-2 - pred_x] + mv_penalty[by - pred_y])*c->penalty_factor;
90 686486 const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)]
91 686486 + (mv_penalty[bx+2 - pred_x] + mv_penalty[by - pred_y])*c->penalty_factor;
92 686486 const int b= score_map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)]
93 686486 + (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) * (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) * (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) * (1 << ME_MAP_MV_BITS) + (mx + 1) + map_generation;
103 av_assert2(c->map[(index+1)&(ME_MAP_SIZE-1)] == key);
104 key = (my) * (1 << ME_MAP_MV_BITS) + (mx - 1) + map_generation;
105 av_assert2(c->map[(index-1)&(ME_MAP_SIZE-1)] == key);
106 #endif
107
2/2
✓ Branch 0 taken 340008 times.
✓ Branch 1 taken 346478 times.
686486 if(t<=b){
108 340008 CHECK_HALF_MV(0, 1, mx ,my-1)
109
2/2
✓ Branch 0 taken 211535 times.
✓ Branch 1 taken 128473 times.
340008 if(l<=r){
110 211535 CHECK_HALF_MV(1, 1, mx-1, my-1)
111
2/2
✓ Branch 0 taken 111876 times.
✓ Branch 1 taken 99659 times.
211535 if(t+r<=b+l){
112 111876 CHECK_HALF_MV(1, 1, mx , my-1)
113 }else{
114 99659 CHECK_HALF_MV(1, 1, mx-1, my )
115 }
116 211535 CHECK_HALF_MV(1, 0, mx-1, my )
117 }else{
118 128473 CHECK_HALF_MV(1, 1, mx , my-1)
119
2/2
✓ Branch 0 taken 66696 times.
✓ Branch 1 taken 61777 times.
128473 if(t+l<=b+r){
120 66696 CHECK_HALF_MV(1, 1, mx-1, my-1)
121 }else{
122 61777 CHECK_HALF_MV(1, 1, mx , my )
123 }
124 128473 CHECK_HALF_MV(1, 0, mx , my )
125 }
126 }else{
127
2/2
✓ Branch 0 taken 129260 times.
✓ Branch 1 taken 217218 times.
346478 if(l<=r){
128
2/2
✓ Branch 0 taken 58699 times.
✓ Branch 1 taken 70561 times.
129260 if(t+l<=b+r){
129 58699 CHECK_HALF_MV(1, 1, mx-1, my-1)
130 }else{
131 70561 CHECK_HALF_MV(1, 1, mx , my )
132 }
133 129260 CHECK_HALF_MV(1, 0, mx-1, my)
134 129260 CHECK_HALF_MV(1, 1, mx-1, my)
135 }else{
136
2/2
✓ Branch 0 taken 105100 times.
✓ Branch 1 taken 112118 times.
217218 if(t+r<=b+l){
137 105100 CHECK_HALF_MV(1, 1, mx , my-1)
138 }else{
139 112118 CHECK_HALF_MV(1, 1, mx-1, my)
140 }
141 217218 CHECK_HALF_MV(1, 0, mx , my)
142 217218 CHECK_HALF_MV(1, 1, mx , my)
143 }
144 346478 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 700364 *mx_ptr = bx;
150 700364 *my_ptr = by;
151
152 700364 return dmin;
153 }
154
155 107295 static int no_sub_motion_search(MPVEncContext *const s,
156 int *mx_ptr, int *my_ptr, int dmin,
157 int src_index, int ref_index,
158 int size, int h)
159 {
160 107295 (*mx_ptr) *= 2;
161 107295 (*my_ptr) *= 2;
162 107295 return dmin;
163 }
164
165 969852 static inline int get_mb_score(MPVEncContext *const s, int mx, int my,
166 int src_index, int ref_index, int size,
167 int h, int add_rate)
168 {
169 969852 MotionEstContext *const c = &s->me;
170 969852 const int penalty_factor= c->mb_penalty_factor;
171 969852 const int flags= c->mb_flags;
172 969852 const int qpel= flags & FLAG_QPEL;
173 969852 const int mask= 1+2*qpel;
174 me_cmp_func cmp_sub, chroma_cmp_sub;
175 int d;
176
177 969852 LOAD_COMMON
178
179 //FIXME factorize
180
181 969852 cmp_sub = c->mb_cmp[size];
182 969852 chroma_cmp_sub = c->mb_cmp[size + 1];
183
184 969852 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
7/8
✓ Branch 0 taken 399192 times.
✓ Branch 1 taken 570660 times.
✓ Branch 2 taken 76684 times.
✓ Branch 3 taken 322508 times.
✓ Branch 4 taken 40698 times.
✓ Branch 5 taken 35986 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 40698 times.
969852 if(add_rate && (mx || my || size>0))
187 358494 d += (mv_penalty[mx - pred_x] + mv_penalty[my - pred_y])*penalty_factor;
188
189 969852 return d;
190 }
191
192 570660 int ff_get_mb_score(MPVEncContext *const s, int mx, int my, int src_index,
193 int ref_index, int size, int h, int add_rate)
194 {
195 570660 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
207 750484 static int qpel_motion_search(MPVEncContext *const s,
208 int *mx_ptr, int *my_ptr, int dmin,
209 int src_index, int ref_index,
210 int size, int h)
211 {
212 750484 MotionEstContext *const c = &s->me;
213 750484 const int mx = *mx_ptr;
214 750484 const int my = *my_ptr;
215 750484 const int penalty_factor= c->sub_penalty_factor;
216 750484 const unsigned map_generation = c->map_generation;
217 750484 const int subpel_quality= c->avctx->me_subpel_quality;
218 750484 uint32_t *map= c->map;
219 me_cmp_func cmpf, chroma_cmpf;
220 me_cmp_func cmp_sub, chroma_cmp_sub;
221
222 750484 LOAD_COMMON
223 750484 int flags= c->sub_flags;
224
225 750484 cmpf = c->me_cmp[size];
226 750484 chroma_cmpf = c->me_cmp[size + 1]; // FIXME: factorize
227 //FIXME factorize
228
229 750484 cmp_sub = c->me_sub_cmp[size];
230 750484 chroma_cmp_sub = c->me_sub_cmp[size + 1];
231
232
2/2
✓ Branch 0 taken 1505 times.
✓ Branch 1 taken 748979 times.
750484 if(c->skip){ //FIXME somehow move up (benchmark)
233 1505 *mx_ptr = 0;
234 1505 *my_ptr = 0;
235 1505 return dmin;
236 }
237
238
2/2
✓ Branch 0 taken 187114 times.
✓ Branch 1 taken 561865 times.
748979 if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
239 187114 dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
240
6/6
✓ Branch 0 taken 40019 times.
✓ Branch 1 taken 147095 times.
✓ Branch 2 taken 23598 times.
✓ Branch 3 taken 16421 times.
✓ Branch 4 taken 711 times.
✓ Branch 5 taken 22887 times.
187114 if(mx || my || size>0)
241 164227 dmin += (mv_penalty[4*mx - pred_x] + mv_penalty[4*my - pred_y])*penalty_factor;
242 }
243
244
6/6
✓ Branch 0 taken 747032 times.
✓ Branch 1 taken 1947 times.
✓ Branch 2 taken 745381 times.
✓ Branch 3 taken 1651 times.
✓ Branch 4 taken 745099 times.
✓ Branch 5 taken 282 times.
748979 if (mx > xmin && mx < xmax &&
245
2/2
✓ Branch 0 taken 744612 times.
✓ Branch 1 taken 487 times.
745099 my > ymin && my < ymax) {
246 744612 int bx=4*mx, by=4*my;
247 744612 int d= dmin;
248 int i, nx, ny;
249 744612 const int index = my * (1 << ME_MAP_SHIFT) + mx;
250 744612 const int t= score_map[(index-(1<<ME_MAP_SHIFT) )&(ME_MAP_SIZE-1)];
251 744612 const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)];
252 744612 const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)];
253 744612 const int b= score_map[(index+(1<<ME_MAP_SHIFT) )&(ME_MAP_SIZE-1)];
254 744612 const int c= score_map[(index )&(ME_MAP_SIZE-1)];
255 int best[8];
256 int best_pos[8][2];
257
258 744612 memset(best, 64, sizeof(int)*8);
259
2/2
✓ Branch 0 taken 246148 times.
✓ Branch 1 taken 498464 times.
744612 if(s->me.dia_size>=2){
260 246148 const int tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
261 246148 const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
262 246148 const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
263 246148 const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
264
265
2/2
✓ Branch 0 taken 1723036 times.
✓ Branch 1 taken 246148 times.
1969184 for(ny= -3; ny <= 3; ny++){
266
2/2
✓ Branch 0 taken 12061252 times.
✓ Branch 1 taken 1723036 times.
13784288 for(nx= -3; nx <= 3; nx++){
267 //FIXME this could overflow (unlikely though)
268 12061252 const int64_t t2= nx*nx*(tr + tl - 2*t) + 4*nx*(tr-tl) + 32*t;
269 12061252 const int64_t c2= nx*nx*( r + l - 2*c) + 4*nx*( r- l) + 32*c;
270 12061252 const int64_t b2= nx*nx*(br + bl - 2*b) + 4*nx*(br-bl) + 32*b;
271 12061252 int score= (ny*ny*(b2 + t2 - 2*c2) + 4*ny*(b2 - t2) + 32*c2 + 512)>>10;
272 int i;
273
274
4/4
✓ Branch 0 taken 1723036 times.
✓ Branch 1 taken 10338216 times.
✓ Branch 2 taken 246148 times.
✓ Branch 3 taken 1476888 times.
12061252 if((nx&3)==0 && (ny&3)==0) continue;
275
276 11815104 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
2/2
✓ Branch 0 taken 65050301 times.
✓ Branch 1 taken 5690067 times.
70740368 for(i=0; i<8; i++){
282
2/2
✓ Branch 0 taken 6125037 times.
✓ Branch 1 taken 58925264 times.
65050301 if(score < best[i]){
283 6125037 memmove(&best[i+1], &best[i], sizeof(int)*(7-i));
284 6125037 memmove(&best_pos[i + 1], &best_pos[i], sizeof(*best_pos) * (7 - i));
285 6125037 best[i]= score;
286 6125037 best_pos[i][0]= nx + 4*mx;
287 6125037 best_pos[i][1]= ny + 4*my;
288 6125037 break;
289 }
290 }
291 }
292 }
293 }else{
294 int tl;
295 //FIXME this could overflow (unlikely though)
296 498464 const int cx = 4*(r - l);
297 498464 const int cx2= r + l - 2*c;
298 498464 const int cy = 4*(b - t);
299 498464 const int cy2= b + t - 2*c;
300 int cxy;
301
302 498464 if (map[(index - (1 << ME_MAP_SHIFT) - 1) & (ME_MAP_SIZE - 1)] ==
303
2/2
✓ Branch 0 taken 234468 times.
✓ Branch 1 taken 263996 times.
498464 (my - 1) * (1 << ME_MAP_MV_BITS) + (mx - 1) + map_generation) {
304 234468 tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
305 }else{
306 263996 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
307 }
308
309 498464 cxy= 2*tl + (cx + cy)/4 - (cx2 + cy2) - 2*c;
310
311 av_assert2(16*cx2 + 4*cx + 32*c == 32*r);
312 av_assert2(16*cx2 - 4*cx + 32*c == 32*l);
313 av_assert2(16*cy2 + 4*cy + 32*c == 32*b);
314 av_assert2(16*cy2 - 4*cy + 32*c == 32*t);
315 av_assert2(16*cxy + 16*cy2 + 16*cx2 - 4*cy - 4*cx + 32*c == 32*tl);
316
317
2/2
✓ Branch 0 taken 3489248 times.
✓ Branch 1 taken 498464 times.
3987712 for(ny= -3; ny <= 3; ny++){
318
2/2
✓ Branch 0 taken 24424736 times.
✓ Branch 1 taken 3489248 times.
27913984 for(nx= -3; nx <= 3; nx++){
319 //FIXME this could overflow (unlikely though)
320 24424736 int score= ny*nx*cxy + nx*nx*cx2 + ny*ny*cy2 + nx*cx + ny*cy + 32*c; //FIXME factor
321 int i;
322
323
4/4
✓ Branch 0 taken 3489248 times.
✓ Branch 1 taken 20935488 times.
✓ Branch 2 taken 498464 times.
✓ Branch 3 taken 2990784 times.
24424736 if((nx&3)==0 && (ny&3)==0) continue;
324
325 23926272 score += 32*(mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;
326 // if(nx&1) score-=32*c->penalty_factor;
327 // if(ny&1) score-=32*c->penalty_factor;
328
329
2/2
✓ Branch 0 taken 130452504 times.
✓ Branch 1 taken 11247196 times.
141699700 for(i=0; i<8; i++){
330
2/2
✓ Branch 0 taken 12679076 times.
✓ Branch 1 taken 117773428 times.
130452504 if(score < best[i]){
331 12679076 memmove(&best[i+1], &best[i], sizeof(int)*(7-i));
332 12679076 memmove(best_pos[i + 1], best_pos[i], sizeof(best_pos[0]) * (7 - i));
333 12679076 best[i]= score;
334 12679076 best_pos[i][0]= nx + 4*mx;
335 12679076 best_pos[i][1]= ny + 4*my;
336 12679076 break;
337 }
338 }
339 }
340 }
341 }
342
2/2
✓ Branch 0 taken 5956896 times.
✓ Branch 1 taken 744612 times.
6701508 for(i=0; i<subpel_quality; i++){
343 5956896 nx= best_pos[i][0];
344 5956896 ny= best_pos[i][1];
345 5956896 CHECK_QUARTER_MV(nx&3, ny&3, nx>>2, ny>>2)
346 }
347
348 av_assert2(bx >= xmin*4 && bx <= xmax*4 && by >= ymin*4 && by <= ymax*4);
349
350 744612 *mx_ptr = bx;
351 744612 *my_ptr = by;
352 }else{
353 4367 *mx_ptr =4*mx;
354 4367 *my_ptr =4*my;
355 }
356
357 748979 return dmin;
358 }
359
360
361 #define CHECK_MV(x,y)\
362 {\
363 const unsigned key = ((unsigned)(y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
364 const int index= (((unsigned)(y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
365 av_assert2((x) >= xmin);\
366 av_assert2((x) <= xmax);\
367 av_assert2((y) >= ymin);\
368 av_assert2((y) <= ymax);\
369 if(map[index]!=key){\
370 d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
371 map[index]= key;\
372 score_map[index]= d;\
373 d += (mv_penalty[((x)*(1<<shift))-pred_x] + mv_penalty[((y)*(1<<shift))-pred_y])*penalty_factor;\
374 COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\
375 }\
376 }
377
378 #define CHECK_CLIPPED_MV(ax,ay)\
379 {\
380 const int Lx= ax;\
381 const int Ly= ay;\
382 const int Lx2= FFMAX(xmin, FFMIN(Lx, xmax));\
383 const int Ly2= FFMAX(ymin, FFMIN(Ly, ymax));\
384 CHECK_MV(Lx2, Ly2)\
385 }
386
387 #define CHECK_MV_DIR(x,y,new_dir)\
388 {\
389 const unsigned key = ((unsigned)(y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
390 const int index= (((unsigned)(y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
391 if(map[index]!=key){\
392 d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
393 map[index]= key;\
394 score_map[index]= d;\
395 d += (mv_penalty[(int)((unsigned)(x)<<shift)-pred_x] + mv_penalty[(int)((unsigned)(y)<<shift)-pred_y])*penalty_factor;\
396 if(d<dmin){\
397 best[0]=x;\
398 best[1]=y;\
399 dmin=d;\
400 next_dir= new_dir;\
401 }\
402 }\
403 }
404
405 #define check(x,y,S,v)\
406 if( (x)<(xmin<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d xmin" #v, xmin, (x), (y), s->c.mb_x, s->c.mb_y);\
407 if( (x)>(xmax<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d xmax" #v, xmax, (x), (y), s->c.mb_x, s->c.mb_y);\
408 if( (y)<(ymin<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d ymin" #v, ymin, (x), (y), s->c.mb_x, s->c.mb_y);\
409 if( (y)>(ymax<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d ymax" #v, ymax, (x), (y), s->c.mb_x, s->c.mb_y);\
410
411 #define LOAD_COMMON2\
412 uint32_t *map= c->map;\
413 const int qpel= flags&FLAG_QPEL;\
414 const int shift= 1+qpel;\
415
416 5839678 static av_always_inline int small_diamond_search(MPVEncContext *const s, int *best, int dmin,
417 int src_index, int ref_index, const int penalty_factor,
418 int size, int h, int flags)
419 {
420 5839678 MotionEstContext *const c = &s->me;
421 me_cmp_func cmpf, chroma_cmpf;
422 5839678 int next_dir=-1;
423 5839678 LOAD_COMMON
424 5839678 LOAD_COMMON2
425 5839678 unsigned map_generation = c->map_generation;
426
427 5839678 cmpf = c->me_cmp[size];
428 5839678 chroma_cmpf = c->me_cmp[size + 1];
429
430 { /* ensure that the best point is in the MAP as h/qpel refinement needs it */
431 5839678 const unsigned key = ((unsigned)best[1]<<ME_MAP_MV_BITS) + best[0] + map_generation;
432 5839678 const int index= (((unsigned)best[1]<<ME_MAP_SHIFT) + best[0])&(ME_MAP_SIZE-1);
433
2/2
✓ Branch 0 taken 36890 times.
✓ Branch 1 taken 5802788 times.
5839678 if (map[index] != key) { // this will be executed only very rarely
434 36890 score_map[index]= cmp(s, best[0], best[1], 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
435 36890 map[index]= key;
436 }
437 }
438
439 1795898 for(;;){
440 int d;
441 7635576 const int dir= next_dir;
442 7635576 const int x= best[0];
443 7635576 const int y= best[1];
444 7635576 next_dir=-1;
445
446
8/8
✓ Branch 0 taken 7053910 times.
✓ Branch 1 taken 581666 times.
✓ Branch 2 taken 6929036 times.
✓ Branch 3 taken 124874 times.
✓ Branch 4 taken 3837076 times.
✓ Branch 5 taken 3091960 times.
✓ Branch 7 taken 606321 times.
✓ Branch 8 taken 3230755 times.
7635576 if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y , 0)
447
8/8
✓ Branch 0 taken 7239384 times.
✓ Branch 1 taken 396192 times.
✓ Branch 2 taken 7059131 times.
✓ Branch 3 taken 180253 times.
✓ Branch 4 taken 4217872 times.
✓ Branch 5 taken 2841259 times.
✓ Branch 7 taken 400505 times.
✓ Branch 8 taken 3817367 times.
7635576 if(dir!=3 && y>ymin) CHECK_MV_DIR(x , y-1, 1)
448
8/8
✓ Branch 0 taken 7162580 times.
✓ Branch 1 taken 472996 times.
✓ Branch 2 taken 7051235 times.
✓ Branch 3 taken 111345 times.
✓ Branch 4 taken 4602985 times.
✓ Branch 5 taken 2448250 times.
✓ Branch 7 taken 670238 times.
✓ Branch 8 taken 3932747 times.
7635576 if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y , 2)
449
8/8
✓ Branch 0 taken 7290532 times.
✓ Branch 1 taken 345044 times.
✓ Branch 2 taken 7155512 times.
✓ Branch 3 taken 135020 times.
✓ Branch 4 taken 4898659 times.
✓ Branch 5 taken 2256853 times.
✓ Branch 7 taken 396192 times.
✓ Branch 8 taken 4502467 times.
7635576 if(dir!=1 && y<ymax) CHECK_MV_DIR(x , y+1, 3)
450
451
2/2
✓ Branch 0 taken 5839678 times.
✓ Branch 1 taken 1795898 times.
7635576 if(next_dir==-1){
452 5839678 return dmin;
453 }
454 }
455 }
456
457 ✗ static int funny_diamond_search(MPVEncContext *const s, int *best, int dmin,
458 int src_index, int ref_index, const int penalty_factor,
459 int size, int h, int flags)
460 {
461 ✗ MotionEstContext *const c = &s->me;
462 me_cmp_func cmpf, chroma_cmpf;
463 int dia_size;
464 ✗ LOAD_COMMON
465 ✗ LOAD_COMMON2
466 ✗ unsigned map_generation = c->map_generation;
467
468 ✗ cmpf = c->me_cmp[size];
469 ✗ chroma_cmpf = c->me_cmp[size + 1];
470
471 ✗ for(dia_size=1; dia_size<=4; dia_size++){
472 int dir;
473 ✗ const int x= best[0];
474 ✗ const int y= best[1];
475
476 ✗ if(dia_size&(dia_size-1)) continue;
477
478 ✗ if( x + dia_size > xmax
479 ✗ || x - dia_size < xmin
480 ✗ || y + dia_size > ymax
481 ✗ || y - dia_size < ymin)
482 ✗ continue;
483
484 ✗ for(dir= 0; dir<dia_size; dir+=2){
485 int d;
486
487 ✗ CHECK_MV(x + dir , y + dia_size - dir);
488 ✗ CHECK_MV(x + dia_size - dir, y - dir );
489 ✗ CHECK_MV(x - dir , y - dia_size + dir);
490 ✗ CHECK_MV(x - dia_size + dir, y + dir );
491 }
492
493 ✗ if(x!=best[0] || y!=best[1])
494 ✗ dia_size=0;
495 }
496 ✗ return dmin;
497 }
498
499 ✗ static int hex_search(MPVEncContext *const s, int *best, int dmin,
500 int src_index, int ref_index, const int penalty_factor,
501 int size, int h, int flags, int dia_size)
502 {
503 ✗ MotionEstContext *const c = &s->me;
504 me_cmp_func cmpf, chroma_cmpf;
505 ✗ LOAD_COMMON
506 ✗ LOAD_COMMON2
507 ✗ unsigned map_generation = c->map_generation;
508 int x,y,d;
509 ✗ const int dec= dia_size & (dia_size-1);
510
511 ✗ cmpf = c->me_cmp[size];
512 ✗ chroma_cmpf = c->me_cmp[size + 1];
513
514 ✗ for(;dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){
515 do{
516 ✗ x= best[0];
517 ✗ y= best[1];
518
519 ✗ CHECK_CLIPPED_MV(x -dia_size , y);
520 ✗ CHECK_CLIPPED_MV(x+ dia_size , y);
521 ✗ CHECK_CLIPPED_MV(x+( dia_size>>1), y+dia_size);
522 ✗ CHECK_CLIPPED_MV(x+( dia_size>>1), y-dia_size);
523 ✗ if(dia_size>1){
524 ✗ CHECK_CLIPPED_MV(x+(-dia_size>>1), y+dia_size);
525 ✗ CHECK_CLIPPED_MV(x+(-dia_size>>1), y-dia_size);
526 }
527 ✗ }while(best[0] != x || best[1] != y);
528 }
529
530 ✗ return dmin;
531 }
532
533 ✗ static int l2s_dia_search(MPVEncContext *const s, int *best, int dmin,
534 int src_index, int ref_index, const int penalty_factor,
535 int size, int h, int flags)
536 {
537 ✗ MotionEstContext *const c = &s->me;
538 me_cmp_func cmpf, chroma_cmpf;
539 ✗ LOAD_COMMON
540 ✗ LOAD_COMMON2
541 ✗ unsigned map_generation = c->map_generation;
542 int x,y,i,d;
543 ✗ int dia_size= c->dia_size&0xFF;
544 ✗ const int dec= dia_size & (dia_size-1);
545 static const int hex[8][2]={{-2, 0}, {-1,-1}, { 0,-2}, { 1,-1},
546 { 2, 0}, { 1, 1}, { 0, 2}, {-1, 1}};
547
548 ✗ cmpf = c->me_cmp[size];
549 ✗ chroma_cmpf = c->me_cmp[size + 1];
550
551 ✗ for(; dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){
552 do{
553 ✗ x= best[0];
554 ✗ y= best[1];
555 ✗ for(i=0; i<8; i++){
556 ✗ CHECK_CLIPPED_MV(x+hex[i][0]*dia_size, y+hex[i][1]*dia_size);
557 }
558 ✗ }while(best[0] != x || best[1] != y);
559 }
560
561 ✗ x= best[0];
562 ✗ y= best[1];
563 ✗ CHECK_CLIPPED_MV(x+1, y);
564 ✗ CHECK_CLIPPED_MV(x, y+1);
565 ✗ CHECK_CLIPPED_MV(x-1, y);
566 ✗ CHECK_CLIPPED_MV(x, y-1);
567
568 ✗ return dmin;
569 }
570
571 ✗ static int umh_search(MPVEncContext *const s, int *best, int dmin,
572 int src_index, int ref_index, const int penalty_factor,
573 int size, int h, int flags)
574 {
575 ✗ MotionEstContext *const c = &s->me;
576 me_cmp_func cmpf, chroma_cmpf;
577 ✗ LOAD_COMMON
578 ✗ LOAD_COMMON2
579 ✗ unsigned map_generation = c->map_generation;
580 int x,y,x2,y2, i, j, d;
581 ✗ const int dia_size= c->dia_size&0xFE;
582 static const int hex[16][2]={{-4,-2}, {-4,-1}, {-4, 0}, {-4, 1}, {-4, 2},
583 { 4,-2}, { 4,-1}, { 4, 0}, { 4, 1}, { 4, 2},
584 {-2, 3}, { 0, 4}, { 2, 3},
585 {-2,-3}, { 0,-4}, { 2,-3},};
586
587 ✗ cmpf = c->me_cmp[size];
588 ✗ chroma_cmpf = c->me_cmp[size + 1];
589
590 ✗ x= best[0];
591 ✗ y= best[1];
592 ✗ for(x2=FFMAX(x-dia_size+1, xmin); x2<=FFMIN(x+dia_size-1,xmax); x2+=2){
593 ✗ CHECK_MV(x2, y);
594 }
595 ✗ for(y2=FFMAX(y-dia_size/2+1, ymin); y2<=FFMIN(y+dia_size/2-1,ymax); y2+=2){
596 ✗ CHECK_MV(x, y2);
597 }
598
599 ✗ x= best[0];
600 ✗ y= best[1];
601 ✗ for(y2=FFMAX(y-2, ymin); y2<=FFMIN(y+2,ymax); y2++){
602 ✗ for(x2=FFMAX(x-2, xmin); x2<=FFMIN(x+2,xmax); x2++){
603 ✗ CHECK_MV(x2, y2);
604 }
605 }
606
607 //FIXME prevent the CLIP stuff
608
609 ✗ for(j=1; j<=dia_size/4; j++){
610 ✗ for(i=0; i<16; i++){
611 ✗ CHECK_CLIPPED_MV(x+hex[i][0]*j, y+hex[i][1]*j);
612 }
613 }
614
615 ✗ return hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, 2);
616 }
617
618 ✗ static int full_search(MPVEncContext *const s, int *best, int dmin,
619 int src_index, int ref_index, const int penalty_factor,
620 int size, int h, int flags)
621 {
622 ✗ MotionEstContext *const c = &s->me;
623 me_cmp_func cmpf, chroma_cmpf;
624 ✗ LOAD_COMMON
625 ✗ LOAD_COMMON2
626 ✗ unsigned map_generation = c->map_generation;
627 int x,y, d;
628 ✗ const int dia_size= c->dia_size&0xFF;
629
630 ✗ cmpf = c->me_cmp[size];
631 ✗ chroma_cmpf = c->me_cmp[size + 1];
632
633 ✗ for(y=FFMAX(-dia_size, ymin); y<=FFMIN(dia_size,ymax); y++){
634 ✗ for(x=FFMAX(-dia_size, xmin); x<=FFMIN(dia_size,xmax); x++){
635 ✗ CHECK_MV(x, y);
636 }
637 }
638
639 ✗ x= best[0];
640 ✗ y= best[1];
641 ✗ d= dmin;
642 ✗ CHECK_CLIPPED_MV(x , y);
643 ✗ CHECK_CLIPPED_MV(x+1, y);
644 ✗ CHECK_CLIPPED_MV(x, y+1);
645 ✗ CHECK_CLIPPED_MV(x-1, y);
646 ✗ CHECK_CLIPPED_MV(x, y-1);
647 ✗ best[0]= x;
648 ✗ best[1]= y;
649
650 ✗ return d;
651 }
652
653 #define SAB_CHECK_MV(ax,ay)\
654 {\
655 const unsigned key = ((ay)<<ME_MAP_MV_BITS) + (ax) + map_generation;\
656 const int index= (((ay)<<ME_MAP_SHIFT) + (ax))&(ME_MAP_SIZE-1);\
657 if(map[index]!=key){\
658 d= cmp(s, ax, ay, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
659 map[index]= key;\
660 score_map[index]= d;\
661 d += (mv_penalty[((ax)<<shift)-pred_x] + mv_penalty[((ay)<<shift)-pred_y])*penalty_factor;\
662 if(d < minima[minima_count-1].height){\
663 int j=0;\
664 \
665 while(d >= minima[j].height) j++;\
666 \
667 memmove(&minima [j+1], &minima [j], (minima_count - j - 1)*sizeof(Minima));\
668 \
669 minima[j].checked= 0;\
670 minima[j].height= d;\
671 minima[j].x= ax;\
672 minima[j].y= ay;\
673 \
674 i=-1;\
675 continue;\
676 }\
677 }\
678 }
679
680 #define MAX_SAB_SIZE ME_MAP_SIZE
681 ✗ static int sab_diamond_search(MPVEncContext *const s, int *best, int dmin,
682 int src_index, int ref_index, const int penalty_factor,
683 int size, int h, int flags)
684 {
685 ✗ MotionEstContext *const c = &s->me;
686 me_cmp_func cmpf, chroma_cmpf;
687 Minima minima[MAX_SAB_SIZE];
688 ✗ const int minima_count= FFABS(c->dia_size);
689 int i, j;
690 ✗ LOAD_COMMON
691 ✗ LOAD_COMMON2
692 ✗ unsigned map_generation = c->map_generation;
693
694 av_assert1(minima_count <= MAX_SAB_SIZE);
695
696 ✗ cmpf = c->me_cmp[size];
697 ✗ chroma_cmpf = c->me_cmp[size + 1];
698
699 /*Note j<MAX_SAB_SIZE is needed if MAX_SAB_SIZE < ME_MAP_SIZE as j can
700 become larger due to MVs overflowing their ME_MAP_MV_BITS bits space in map
701 */
702 ✗ for(j=i=0; i<ME_MAP_SIZE && j<MAX_SAB_SIZE; i++){
703 ✗ uint32_t key= map[i];
704
705 ✗ key += (1<<(ME_MAP_MV_BITS-1)) + (1<<(2*ME_MAP_MV_BITS-1));
706
707 ✗ if ((key & (-(1 << (2 * ME_MAP_MV_BITS)))) != map_generation)
708 ✗ continue;
709
710 ✗ minima[j].height= score_map[i];
711 ✗ minima[j].x= key & ((1<<ME_MAP_MV_BITS)-1); key>>=ME_MAP_MV_BITS;
712 ✗ minima[j].y= key & ((1<<ME_MAP_MV_BITS)-1);
713 ✗ minima[j].x-= (1<<(ME_MAP_MV_BITS-1));
714 ✗ minima[j].y-= (1<<(ME_MAP_MV_BITS-1));
715
716 // all entries in map should be in range except if the mv overflows their ME_MAP_MV_BITS bits space
717 ✗ if( minima[j].x > xmax || minima[j].x < xmin
718 ✗ || minima[j].y > ymax || minima[j].y < ymin)
719 ✗ continue;
720
721 ✗ minima[j].checked=0;
722 ✗ if(minima[j].x || minima[j].y)
723 ✗ minima[j].height+= (mv_penalty[((minima[j].x)<<shift)-pred_x] + mv_penalty[((minima[j].y)<<shift)-pred_y])*penalty_factor;
724
725 ✗ j++;
726 }
727
728 ✗ AV_QSORT(minima, j, Minima, minima_cmp);
729
730 ✗ for(; j<minima_count; j++){
731 ✗ minima[j].height=256*256*256*64;
732 ✗ minima[j].checked=0;
733 ✗ minima[j].x= minima[j].y=0;
734 }
735
736 ✗ for(i=0; i<minima_count; i++){
737 ✗ const int x= minima[i].x;
738 ✗ const int y= minima[i].y;
739 int d;
740
741 ✗ if(minima[i].checked) continue;
742
743 ✗ if( x >= xmax || x <= xmin
744 ✗ || y >= ymax || y <= ymin)
745 ✗ continue;
746
747 ✗ SAB_CHECK_MV(x-1, y)
748 ✗ SAB_CHECK_MV(x+1, y)
749 ✗ SAB_CHECK_MV(x , y-1)
750 ✗ SAB_CHECK_MV(x , y+1)
751
752 ✗ minima[i].checked= 1;
753 }
754
755 ✗ best[0]= minima[0].x;
756 ✗ best[1]= minima[0].y;
757 ✗ dmin= minima[0].height;
758
759 ✗ if( best[0] < xmax && best[0] > xmin
760 ✗ && best[1] < ymax && best[1] > ymin){
761 int d;
762 // ensure that the reference samples for hpel refinement are in the map
763 ✗ CHECK_MV(best[0]-1, best[1])
764 ✗ CHECK_MV(best[0]+1, best[1])
765 ✗ CHECK_MV(best[0], best[1]-1)
766 ✗ CHECK_MV(best[0], best[1]+1)
767 }
768 ✗ return dmin;
769 }
770
771 250499 static int var_diamond_search(MPVEncContext *const s, int *best, int dmin,
772 int src_index, int ref_index, const int penalty_factor,
773 int size, int h, int flags)
774 {
775 250499 MotionEstContext *const c = &s->me;
776 me_cmp_func cmpf, chroma_cmpf;
777 int dia_size;
778 250499 LOAD_COMMON
779 250499 LOAD_COMMON2
780 250499 unsigned map_generation = c->map_generation;
781
782 250499 cmpf = c->me_cmp[size];
783 250499 chroma_cmpf = c->me_cmp[size + 1];
784
785
2/2
✓ Branch 0 taken 777884 times.
✓ Branch 1 taken 250499 times.
1028383 for(dia_size=1; dia_size<=c->dia_size; dia_size++){
786 int dir, start, end;
787 777884 const int x= best[0];
788 777884 const int y= best[1];
789
790 777884 start= FFMAX(0, y + dia_size - ymax);
791 777884 end = FFMIN(dia_size, xmax - x + 1);
792
2/2
✓ Branch 0 taken 1069908 times.
✓ Branch 1 taken 777884 times.
1847792 for(dir= start; dir<end; dir++){
793 int d;
794
795 //check(x + dir,y + dia_size - dir,0, a0)
796
2/2
✓ Branch 0 taken 772620 times.
✓ Branch 1 taken 297288 times.
1069908 CHECK_MV(x + dir , y + dia_size - dir);
797 }
798
799 777884 start= FFMAX(0, x + dia_size - xmax);
800 777884 end = FFMIN(dia_size, y - ymin + 1);
801
2/2
✓ Branch 0 taken 1069932 times.
✓ Branch 1 taken 777884 times.
1847816 for(dir= start; dir<end; dir++){
802 int d;
803
804 //check(x + dia_size - dir, y - dir,0, a1)
805
2/2
✓ Branch 0 taken 788864 times.
✓ Branch 1 taken 281068 times.
1069932 CHECK_MV(x + dia_size - dir, y - dir );
806 }
807
808 777884 start= FFMAX(0, -y + dia_size + ymin );
809 777884 end = FFMIN(dia_size, x - xmin + 1);
810
2/2
✓ Branch 0 taken 1069802 times.
✓ Branch 1 taken 777884 times.
1847686 for(dir= start; dir<end; dir++){
811 int d;
812
813 //check(x - dir,y - dia_size + dir,0, a2)
814
2/2
✓ Branch 0 taken 618504 times.
✓ Branch 1 taken 451298 times.
1069802 CHECK_MV(x - dir , y - dia_size + dir);
815 }
816
817 777884 start= FFMAX(0, -x + dia_size + xmin );
818 777884 end = FFMIN(dia_size, ymax - y + 1);
819
2/2
✓ Branch 0 taken 1069954 times.
✓ Branch 1 taken 777884 times.
1847838 for(dir= start; dir<end; dir++){
820 int d;
821
822 //check(x - dia_size + dir, y + dir,0, a3)
823
2/2
✓ Branch 0 taken 661699 times.
✓ Branch 1 taken 408255 times.
1069954 CHECK_MV(x - dia_size + dir, y + dir );
824 }
825
826
4/4
✓ Branch 0 taken 649717 times.
✓ Branch 1 taken 128167 times.
✓ Branch 2 taken 107142 times.
✓ Branch 3 taken 542575 times.
777884 if(x!=best[0] || y!=best[1])
827 235309 dia_size=0;
828 }
829 250499 return dmin;
830 }
831
832 6090177 static av_always_inline int diamond_search(MPVEncContext *const s, int *best, int dmin,
833 int src_index, int ref_index, const int penalty_factor,
834 int size, int h, int flags){
835 6090177 MotionEstContext *const c = &s->me;
836
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6090177 times.
6090177 if(c->dia_size==-1)
837 ✗ return funny_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6090177 times.
6090177 else if(c->dia_size<-1)
839 ✗ return sab_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
840
2/2
✓ Branch 0 taken 5839678 times.
✓ Branch 1 taken 250499 times.
6090177 else if(c->dia_size<2)
841 5839678 return small_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 250499 times.
250499 else if(c->dia_size>1024)
843 ✗ return full_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 250499 times.
250499 else if(c->dia_size>768)
845 ✗ return umh_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 250499 times.
250499 else if(c->dia_size>512)
847 ✗ return hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, c->dia_size&0xFF);
848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 250499 times.
250499 else if(c->dia_size>256)
849 ✗ return l2s_dia_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
850 else
851 250499 return var_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
852 }
853
854 /**
855 @param P a list of candidate mvs to check before starting the
856 iterative search. If one of the candidates is close to the optimal mv, then
857 it takes fewer iterations. And it increases the chance that we find the
858 optimal mv.
859 */
860 4072537 static av_always_inline int epzs_motion_search_internal(MPVEncContext *const s, int *mx_ptr, int *my_ptr,
861 int P[10][2], int src_index, int ref_index, const int16_t (*last_mv)[2],
862 int ref_mv_scale, int flags, int size, int h)
863 {
864 4072537 MotionEstContext *const c = &s->me;
865 4072537 int best[2]={0, 0}; /**< x and y coordinates of the best motion vector.
866 i.e. the difference between the position of the
867 block currently being encoded and the position of
868 the block chosen to predict it from. */
869 int d; ///< the score (cmp + penalty) of any given mv
870 int dmin; /**< the best value of d, i.e. the score
871 corresponding to the mv stored in best[]. */
872 unsigned map_generation;
873 int penalty_factor;
874 4072537 const int ref_mv_stride= s->c.mb_stride; //pass as arg FIXME
875 4072537 const int ref_mv_xy = s->c.mb_x + s->c.mb_y * ref_mv_stride; // add to last_mv before passing FIXME
876 me_cmp_func cmpf, chroma_cmpf;
877
878 4072537 LOAD_COMMON
879 4072537 LOAD_COMMON2
880
881
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4072537 times.
4072537 if(c->pre_pass){
882 ✗ penalty_factor= c->pre_penalty_factor;
883 ✗ cmpf = c->me_pre_cmp[size];
884 ✗ chroma_cmpf = c->me_pre_cmp[size + 1];
885 }else{
886 4072537 penalty_factor= c->penalty_factor;
887 4072537 cmpf = c->me_cmp[size];
888 4072537 chroma_cmpf = c->me_cmp[size + 1];
889 }
890
891 4072537 map_generation= update_map_generation(c);
892
893 av_assert2(cmpf);
894 4072537 dmin= cmp(s, 0, 0, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
895 4072537 map[0]= map_generation;
896 4072537 score_map[0]= dmin;
897
898 //FIXME precalc first term below?
899
4/4
✓ Branch 0 taken 989017 times.
✓ Branch 1 taken 3083520 times.
✓ Branch 2 taken 184119 times.
✓ Branch 3 taken 804898 times.
4072537 if ((s->c.pict_type == AV_PICTURE_TYPE_B && !(c->flags & FLAG_DIRECT)) ||
900
2/2
✓ Branch 0 taken 156714 times.
✓ Branch 1 taken 3110925 times.
3267639 s->mpv_flags & FF_MPV_FLAG_MV0)
901 961612 dmin += (mv_penalty[pred_x] + mv_penalty[pred_y])*penalty_factor;
902
903 /* first line */
904
2/2
✓ Branch 0 taken 265563 times.
✓ Branch 1 taken 3806974 times.
4072537 if (s->c.first_slice_line) {
905
2/2
✓ Branch 0 taken 189736 times.
✓ Branch 1 taken 75827 times.
265563 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
906
2/2
✓ Branch 0 taken 128177 times.
✓ Branch 1 taken 137386 times.
265563 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
907 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
908 }else{
909
2/2
✓ Branch 0 taken 468941 times.
✓ Branch 1 taken 3338033 times.
3806974 if (dmin < ((h * h * c->avctx->mv0_threshold) >> 8)
910 468941 && ( P_LEFT[0] |P_LEFT[1]
911 468941 |P_TOP[0] |P_TOP[1]
912
2/2
✓ Branch 0 taken 414672 times.
✓ Branch 1 taken 54269 times.
468941 |P_TOPRIGHT[0]|P_TOPRIGHT[1])==0){
913 414672 *mx_ptr= 0;
914 414672 *my_ptr= 0;
915 414672 c->skip=1;
916 414672 return dmin;
917 }
918
2/2
✓ Branch 0 taken 3066285 times.
✓ Branch 1 taken 326017 times.
3392302 CHECK_MV( P_MEDIAN[0] >>shift , P_MEDIAN[1] >>shift)
919
2/2
✓ Branch 0 taken 3341687 times.
✓ Branch 1 taken 50615 times.
3392302 CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift) , (P_MEDIAN[1]>>shift)-1)
920
2/2
✓ Branch 0 taken 3224704 times.
✓ Branch 1 taken 167598 times.
3392302 CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift) , (P_MEDIAN[1]>>shift)+1)
921
2/2
✓ Branch 0 taken 3276443 times.
✓ Branch 1 taken 115859 times.
3392302 CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)-1, (P_MEDIAN[1]>>shift) )
922
2/2
✓ Branch 0 taken 3244844 times.
✓ Branch 1 taken 147458 times.
3392302 CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)+1, (P_MEDIAN[1]>>shift) )
923
2/2
✓ Branch 0 taken 1260198 times.
✓ Branch 1 taken 2132104 times.
3392302 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
924 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
925
2/2
✓ Branch 0 taken 732321 times.
✓ Branch 1 taken 2659981 times.
3392302 CHECK_MV(P_LEFT[0] >>shift, P_LEFT[1] >>shift)
926
2/2
✓ Branch 0 taken 358068 times.
✓ Branch 1 taken 3034234 times.
3392302 CHECK_MV(P_TOP[0] >>shift, P_TOP[1] >>shift)
927
2/2
✓ Branch 0 taken 511058 times.
✓ Branch 1 taken 2881244 times.
3392302 CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
928 }
929
2/2
✓ Branch 0 taken 2521111 times.
✓ Branch 1 taken 1136754 times.
3657865 if(dmin>h*h*4){
930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2521111 times.
2521111 if(c->pre_pass){
931 ✗ CHECK_CLIPPED_MV((last_mv[ref_mv_xy-1][0]*ref_mv_scale + (1<<15))>>16,
932 (last_mv[ref_mv_xy-1][1]*ref_mv_scale + (1<<15))>>16)
933 ✗ if(!s->c.first_slice_line)
934 ✗ CHECK_CLIPPED_MV((last_mv[ref_mv_xy-ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
935 (last_mv[ref_mv_xy-ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
936 }else{
937
2/2
✓ Branch 0 taken 601846 times.
✓ Branch 1 taken 1919265 times.
2521111 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
938 (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
939
2/2
✓ Branch 0 taken 2086871 times.
✓ Branch 1 taken 434240 times.
2521111 if(s->c.mb_y+1<s->c.end_mb_y) //FIXME replace at least with last_slice_line
940
2/2
✓ Branch 0 taken 542304 times.
✓ Branch 1 taken 1544567 times.
2086871 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
941 (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
942 }
943 }
944
945
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3657865 times.
3657865 if(c->avctx->last_predictor_count){
946 ✗ const int count= c->avctx->last_predictor_count;
947 ✗ const int xstart= FFMAX(0, s->c.mb_x - count);
948 ✗ const int ystart= FFMAX(0, s->c.mb_y - count);
949 ✗ const int xend= FFMIN(s->c.mb_width , s->c.mb_x + count + 1);
950 ✗ const int yend= FFMIN(s->c.mb_height, s->c.mb_y + count + 1);
951 int mb_y;
952
953 ✗ for(mb_y=ystart; mb_y<yend; mb_y++){
954 int mb_x;
955 ✗ for(mb_x=xstart; mb_x<xend; mb_x++){
956 ✗ const int xy= mb_x + 1 + (mb_y + 1)*ref_mv_stride;
957 ✗ int mx= (last_mv[xy][0]*ref_mv_scale + (1<<15))>>16;
958 ✗ int my= (last_mv[xy][1]*ref_mv_scale + (1<<15))>>16;
959
960 ✗ if(mx>xmax || mx<xmin || my>ymax || my<ymin) continue;
961 ✗ CHECK_MV(mx,my)
962 }
963 }
964 }
965
966 //check(best[0],best[1],0, b0)
967 3657865 dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
968
969 //check(best[0],best[1],0, b1)
970 3657865 *mx_ptr= best[0];
971 3657865 *my_ptr= best[1];
972
973 3657865 return dmin;
974 }
975
976 //this function is dedicated to the brain damaged gcc
977 4072537 int ff_epzs_motion_search(MPVEncContext *const s, int *mx_ptr, int *my_ptr,
978 int P[10][2], int src_index, int ref_index,
979 const int16_t (*last_mv)[2], int ref_mv_scale,
980 int size, int h)
981 {
982 4072537 MotionEstContext *const c = &s->me;
983 //FIXME convert other functions in the same way if faster
984
4/6
✓ Branch 0 taken 3232870 times.
✓ Branch 1 taken 839667 times.
✓ Branch 2 taken 3232870 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3232870 times.
✗ Branch 5 not taken.
4072537 if(c->flags==0 && h==16 && size==0){
985 3232870 return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, 0, 0, 16);
986 // case FLAG_QPEL:
987 // return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, FLAG_QPEL);
988 }else{
989 839667 return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, c->flags, size, h);
990 }
991 }
992
993 2432312 static int epzs_motion_search2(MPVEncContext *const s,
994 int *mx_ptr, int *my_ptr, int P[10][2],
995 int src_index, int ref_index, const int16_t (*last_mv)[2],
996 int ref_mv_scale, const int size)
997 {
998 2432312 MotionEstContext *const c = &s->me;
999 2432312 int best[2]={0, 0};
1000 int d, dmin;
1001 unsigned map_generation;
1002 2432312 const int penalty_factor= c->penalty_factor;
1003 2432312 const int h=8;
1004 2432312 const int ref_mv_stride= s->c.mb_stride;
1005 2432312 const int ref_mv_xy= s->c.mb_x + s->c.mb_y *ref_mv_stride;
1006 me_cmp_func cmpf, chroma_cmpf;
1007 2432312 LOAD_COMMON
1008 2432312 int flags= c->flags;
1009 2432312 LOAD_COMMON2
1010
1011 2432312 cmpf = c->me_cmp[size];
1012 2432312 chroma_cmpf = c->me_cmp[size + 1];
1013
1014 2432312 map_generation= update_map_generation(c);
1015
1016 2432312 dmin = 1000000;
1017
1018 /* first line */
1019
2/2
✓ Branch 0 taken 186852 times.
✓ Branch 1 taken 2245460 times.
2432312 if (s->c.first_slice_line) {
1020
1/2
✓ Branch 0 taken 186852 times.
✗ Branch 1 not taken.
186852 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1021
2/2
✓ Branch 0 taken 159821 times.
✓ Branch 1 taken 27031 times.
186852 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
2/2
✓ Branch 0 taken 111775 times.
✓ Branch 1 taken 75077 times.
186852 CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
1024 }else{
1025
1/2
✓ Branch 0 taken 2245460 times.
✗ Branch 1 not taken.
2245460 CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
1026 //FIXME try some early stop
1027
2/2
✓ Branch 0 taken 1341104 times.
✓ Branch 1 taken 904356 times.
2245460 CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)
1028
2/2
✓ Branch 0 taken 873543 times.
✓ Branch 1 taken 1371917 times.
2245460 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1029
2/2
✓ Branch 0 taken 549302 times.
✓ Branch 1 taken 1696158 times.
2245460 CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift)
1030
2/2
✓ Branch 0 taken 763645 times.
✓ Branch 1 taken 1481815 times.
2245460 CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
1031
2/2
✓ Branch 0 taken 1593133 times.
✓ Branch 1 taken 652327 times.
2245460 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
2/2
✓ Branch 0 taken 2129008 times.
✓ Branch 1 taken 303304 times.
2432312 if(dmin>64*4){
1035
2/2
✓ Branch 0 taken 842101 times.
✓ Branch 1 taken 1286907 times.
2129008 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
2/2
✓ Branch 0 taken 1960501 times.
✓ Branch 1 taken 168507 times.
2129008 if(s->c.mb_y+1<s->c.end_mb_y) //FIXME replace at least with last_slice_line
1038
2/2
✓ Branch 0 taken 801470 times.
✓ Branch 1 taken 1159031 times.
1960501 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 2432312 dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
1043
1044 2432312 *mx_ptr= best[0];
1045 2432312 *my_ptr= best[1];
1046
1047 2432312 return dmin;
1048 }
1049