FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavfilter/vf_minterpolate.c
Date: 2026-11-01 05:14:56
Exec Total Coverage
Lines: 302 620 48.7%
Functions: 13 19 68.4%
Branches: 143 408 35.0%

Line Branch Exec Source
1 /**
2 * Copyright (c) 2014-2015 Michael Niedermayer <michaelni@gmx.at>
3 * Copyright (c) 2016 Davinder Singh (DSM_) <ds.mudhar<@gmail.com>
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 #include "motion_estimation.h"
23 #include "libavcodec/mathops.h"
24 #include "libavutil/common.h"
25 #include "libavutil/mem.h"
26 #include "libavutil/opt.h"
27 #include "libavutil/pixdesc.h"
28 #include "avfilter.h"
29 #include "filters.h"
30 #include "video.h"
31 #include "scene_sad.h"
32
33 #define ME_MODE_BIDIR 0
34 #define ME_MODE_BILAT 1
35
36 #define MC_MODE_OBMC 0
37 #define MC_MODE_AOBMC 1
38
39 #define SCD_METHOD_NONE 0
40 #define SCD_METHOD_FDIFF 1
41
42 #define NB_FRAMES 4
43 #define NB_PIXEL_MVS 32
44 #define NB_CLUSTERS 128
45
46 #define ALPHA_MAX 1024
47 #define CLUSTER_THRESHOLD 4
48 #define PX_WEIGHT_MAX 255
49 #define COST_PRED_SCALE 64
50
51 static const uint8_t obmc_linear32[1024] = {
52 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0,
53 0, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 16, 20, 20, 20, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 8, 8, 8, 4, 4, 4, 0,
54 0, 4, 8, 8, 12, 12, 16, 20, 20, 24, 28, 28, 32, 32, 36, 40, 40, 36, 32, 32, 28, 28, 24, 20, 20, 16, 12, 12, 8, 8, 4, 0,
55 0, 4, 8, 12, 16, 20, 24, 28, 28, 32, 36, 40, 44, 48, 52, 56, 56, 52, 48, 44, 40, 36, 32, 28, 28, 24, 20, 16, 12, 8, 4, 0,
56 4, 8, 12, 16, 20, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 68, 64, 60, 56, 52, 48, 44, 40, 32, 28, 24, 20, 16, 12, 8, 4,
57 4, 8, 12, 20, 24, 32, 36, 40, 48, 52, 56, 64, 68, 76, 80, 84, 84, 80, 76, 68, 64, 56, 52, 48, 40, 36, 32, 24, 20, 12, 8, 4,
58 4, 8, 16, 24, 28, 36, 44, 48, 56, 60, 68, 76, 80, 88, 96,100,100, 96, 88, 80, 76, 68, 60, 56, 48, 44, 36, 28, 24, 16, 8, 4,
59 4, 12, 20, 28, 32, 40, 48, 56, 64, 72, 80, 88, 92,100,108,116,116,108,100, 92, 88, 80, 72, 64, 56, 48, 40, 32, 28, 20, 12, 4,
60 4, 12, 20, 28, 40, 48, 56, 64, 72, 80, 88, 96,108,116,124,132,132,124,116,108, 96, 88, 80, 72, 64, 56, 48, 40, 28, 20, 12, 4,
61 4, 16, 24, 32, 44, 52, 60, 72, 80, 92,100,108,120,128,136,148,148,136,128,120,108,100, 92, 80, 72, 60, 52, 44, 32, 24, 16, 4,
62 4, 16, 28, 36, 48, 56, 68, 80, 88,100,112,120,132,140,152,164,164,152,140,132,120,112,100, 88, 80, 68, 56, 48, 36, 28, 16, 4,
63 4, 16, 28, 40, 52, 64, 76, 88, 96,108,120,132,144,156,168,180,180,168,156,144,132,120,108, 96, 88, 76, 64, 52, 40, 28, 16, 4,
64 8, 20, 32, 44, 56, 68, 80, 92,108,120,132,144,156,168,180,192,192,180,168,156,144,132,120,108, 92, 80, 68, 56, 44, 32, 20, 8,
65 8, 20, 32, 48, 60, 76, 88,100,116,128,140,156,168,184,196,208,208,196,184,168,156,140,128,116,100, 88, 76, 60, 48, 32, 20, 8,
66 8, 20, 36, 52, 64, 80, 96,108,124,136,152,168,180,196,212,224,224,212,196,180,168,152,136,124,108, 96, 80, 64, 52, 36, 20, 8,
67 8, 24, 40, 56, 68, 84,100,116,132,148,164,180,192,208,224,240,240,224,208,192,180,164,148,132,116,100, 84, 68, 56, 40, 24, 8,
68 8, 24, 40, 56, 68, 84,100,116,132,148,164,180,192,208,224,240,240,224,208,192,180,164,148,132,116,100, 84, 68, 56, 40, 24, 8,
69 8, 20, 36, 52, 64, 80, 96,108,124,136,152,168,180,196,212,224,224,212,196,180,168,152,136,124,108, 96, 80, 64, 52, 36, 20, 8,
70 8, 20, 32, 48, 60, 76, 88,100,116,128,140,156,168,184,196,208,208,196,184,168,156,140,128,116,100, 88, 76, 60, 48, 32, 20, 8,
71 8, 20, 32, 44, 56, 68, 80, 92,108,120,132,144,156,168,180,192,192,180,168,156,144,132,120,108, 92, 80, 68, 56, 44, 32, 20, 8,
72 4, 16, 28, 40, 52, 64, 76, 88, 96,108,120,132,144,156,168,180,180,168,156,144,132,120,108, 96, 88, 76, 64, 52, 40, 28, 16, 4,
73 4, 16, 28, 36, 48, 56, 68, 80, 88,100,112,120,132,140,152,164,164,152,140,132,120,112,100, 88, 80, 68, 56, 48, 36, 28, 16, 4,
74 4, 16, 24, 32, 44, 52, 60, 72, 80, 92,100,108,120,128,136,148,148,136,128,120,108,100, 92, 80, 72, 60, 52, 44, 32, 24, 16, 4,
75 4, 12, 20, 28, 40, 48, 56, 64, 72, 80, 88, 96,108,116,124,132,132,124,116,108, 96, 88, 80, 72, 64, 56, 48, 40, 28, 20, 12, 4,
76 4, 12, 20, 28, 32, 40, 48, 56, 64, 72, 80, 88, 92,100,108,116,116,108,100, 92, 88, 80, 72, 64, 56, 48, 40, 32, 28, 20, 12, 4,
77 4, 8, 16, 24, 28, 36, 44, 48, 56, 60, 68, 76, 80, 88, 96,100,100, 96, 88, 80, 76, 68, 60, 56, 48, 44, 36, 28, 24, 16, 8, 4,
78 4, 8, 12, 20, 24, 32, 36, 40, 48, 52, 56, 64, 68, 76, 80, 84, 84, 80, 76, 68, 64, 56, 52, 48, 40, 36, 32, 24, 20, 12, 8, 4,
79 4, 8, 12, 16, 20, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 68, 64, 60, 56, 52, 48, 44, 40, 32, 28, 24, 20, 16, 12, 8, 4,
80 0, 4, 8, 12, 16, 20, 24, 28, 28, 32, 36, 40, 44, 48, 52, 56, 56, 52, 48, 44, 40, 36, 32, 28, 28, 24, 20, 16, 12, 8, 4, 0,
81 0, 4, 8, 8, 12, 12, 16, 20, 20, 24, 28, 28, 32, 32, 36, 40, 40, 36, 32, 32, 28, 28, 24, 20, 20, 16, 12, 12, 8, 8, 4, 0,
82 0, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 16, 20, 20, 20, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 8, 8, 8, 4, 4, 4, 0,
83 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0,
84 };
85
86 static const uint8_t obmc_linear16[256] = {
87 0, 4, 4, 8, 8, 12, 12, 16, 16, 12, 12, 8, 8, 4, 4, 0,
88 4, 8, 16, 20, 28, 32, 40, 44, 44, 40, 32, 28, 20, 16, 8, 4,
89 4, 16, 24, 36, 44, 56, 64, 76, 76, 64, 56, 44, 36, 24, 16, 4,
90 8, 20, 36, 48, 64, 76, 92,104,104, 92, 76, 64, 48, 36, 20, 8,
91 8, 28, 44, 64, 80,100,116,136,136,116,100, 80, 64, 44, 28, 8,
92 12, 32, 56, 76,100,120,144,164,164,144,120,100, 76, 56, 32, 12,
93 12, 40, 64, 92,116,144,168,196,196,168,144,116, 92, 64, 40, 12,
94 16, 44, 76,104,136,164,196,224,224,196,164,136,104, 76, 44, 16,
95 16, 44, 76,104,136,164,196,224,224,196,164,136,104, 76, 44, 16,
96 12, 40, 64, 92,116,144,168,196,196,168,144,116, 92, 64, 40, 12,
97 12, 32, 56, 76,100,120,144,164,164,144,120,100, 76, 56, 32, 12,
98 8, 28, 44, 64, 80,100,116,136,136,116,100, 80, 64, 44, 28, 8,
99 8, 20, 36, 48, 64, 76, 92,104,104, 92, 76, 64, 48, 36, 20, 8,
100 4, 16, 24, 36, 44, 56, 64, 76, 76, 64, 56, 44, 36, 24, 16, 4,
101 4, 8, 16, 20, 28, 32, 40, 44, 44, 40, 32, 28, 20, 16, 8, 4,
102 0, 4, 4, 8, 8, 12, 12, 16, 16, 12, 12, 8, 8, 4, 4, 0,
103 };
104
105 static const uint8_t obmc_linear8[64] = {
106 4, 12, 20, 28, 28, 20, 12, 4,
107 12, 36, 60, 84, 84, 60, 36, 12,
108 20, 60,100,140,140,100, 60, 20,
109 28, 84,140,196,196,140, 84, 28,
110 28, 84,140,196,196,140, 84, 28,
111 20, 60,100,140,140,100, 60, 20,
112 12, 36, 60, 84, 84, 60, 36, 12,
113 4, 12, 20, 28, 28, 20, 12, 4,
114 };
115
116 static const uint8_t obmc_linear4[16] = {
117 16, 48, 48, 16,
118 48,144,144, 48,
119 48,144,144, 48,
120 16, 48, 48, 16,
121 };
122
123 static const uint8_t * const obmc_tab_linear[4]= {
124 obmc_linear32, obmc_linear16, obmc_linear8, obmc_linear4
125 };
126
127 enum MIMode {
128 MI_MODE_DUP = 0,
129 MI_MODE_BLEND = 1,
130 MI_MODE_MCI = 2,
131 };
132
133 typedef struct Cluster {
134 int64_t sum[2];
135 int nb;
136 } Cluster;
137
138 typedef struct Block {
139 int16_t mvs[2][2];
140 int cid;
141 uint64_t sbad;
142 int sb;
143 struct Block *subs;
144 } Block;
145
146 typedef struct PixelMVS {
147 int16_t mvs[NB_PIXEL_MVS][2];
148 } PixelMVS;
149
150 typedef struct PixelWeights {
151 uint32_t weights[NB_PIXEL_MVS];
152 } PixelWeights;
153
154 typedef struct PixelRefs {
155 int8_t refs[NB_PIXEL_MVS];
156 int nb;
157 } PixelRefs;
158
159 typedef struct Frame {
160 AVFrame *avf;
161 Block *blocks;
162 } Frame;
163
164 typedef struct MIContext {
165 const AVClass *class;
166 AVMotionEstContext me_ctx;
167 AVRational frame_rate;
168 /* enum MIMode */
169 int mi_mode;
170 int mc_mode;
171 int me_mode;
172 int me_method;
173 int mb_size;
174 int search_param;
175 int vsbmc;
176
177 Frame frames[NB_FRAMES];
178 Cluster clusters[NB_CLUSTERS];
179 Block *int_blocks;
180 PixelMVS *pixel_mvs;
181 PixelWeights *pixel_weights;
182 PixelRefs *pixel_refs;
183 int (*mv_table[3])[2][2];
184 int64_t out_pts;
185 int b_width, b_height, b_count;
186 int log2_mb_size;
187 int bitdepth;
188
189 int scd_method;
190 int scene_changed;
191 ff_scene_sad_fn sad;
192 double prev_mafd;
193 double scd_threshold;
194
195 int log2_chroma_w;
196 int log2_chroma_h;
197 int nb_planes;
198 } MIContext;
199
200 #define OFFSET(x) offsetof(MIContext, x)
201 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
202 #define CONST(name, help, val, u) { name, help, 0, AV_OPT_TYPE_CONST, {.i64=val}, 0, 0, FLAGS, .unit = u }
203
204 static const AVOption minterpolate_options[] = {
205 { "fps", "output's frame rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "60"}, 0, INT_MAX, FLAGS },
206 { "mi_mode", "motion interpolation mode", OFFSET(mi_mode), AV_OPT_TYPE_INT, {.i64 = MI_MODE_MCI}, MI_MODE_DUP, MI_MODE_MCI, FLAGS, .unit = "mi_mode" },
207 CONST("dup", "duplicate frames", MI_MODE_DUP, "mi_mode"),
208 CONST("blend", "blend frames", MI_MODE_BLEND, "mi_mode"),
209 CONST("mci", "motion compensated interpolation", MI_MODE_MCI, "mi_mode"),
210 { "mc_mode", "motion compensation mode", OFFSET(mc_mode), AV_OPT_TYPE_INT, {.i64 = MC_MODE_OBMC}, MC_MODE_OBMC, MC_MODE_AOBMC, FLAGS, .unit = "mc_mode" },
211 CONST("obmc", "overlapped block motion compensation", MC_MODE_OBMC, "mc_mode"),
212 CONST("aobmc", "adaptive overlapped block motion compensation", MC_MODE_AOBMC, "mc_mode"),
213 { "me_mode", "motion estimation mode", OFFSET(me_mode), AV_OPT_TYPE_INT, {.i64 = ME_MODE_BILAT}, ME_MODE_BIDIR, ME_MODE_BILAT, FLAGS, .unit = "me_mode" },
214 CONST("bidir", "bidirectional motion estimation", ME_MODE_BIDIR, "me_mode"),
215 CONST("bilat", "bilateral motion estimation", ME_MODE_BILAT, "me_mode"),
216 { "me", "motion estimation method", OFFSET(me_method), AV_OPT_TYPE_INT, {.i64 = AV_ME_METHOD_EPZS}, AV_ME_METHOD_ESA, AV_ME_METHOD_UMH, FLAGS, .unit = "me" },
217 CONST("esa", "exhaustive search", AV_ME_METHOD_ESA, "me"),
218 CONST("tss", "three step search", AV_ME_METHOD_TSS, "me"),
219 CONST("tdls", "two dimensional logarithmic search", AV_ME_METHOD_TDLS, "me"),
220 CONST("ntss", "new three step search", AV_ME_METHOD_NTSS, "me"),
221 CONST("fss", "four step search", AV_ME_METHOD_FSS, "me"),
222 CONST("ds", "diamond search", AV_ME_METHOD_DS, "me"),
223 CONST("hexbs", "hexagon-based search", AV_ME_METHOD_HEXBS, "me"),
224 CONST("epzs", "enhanced predictive zonal search", AV_ME_METHOD_EPZS, "me"),
225 CONST("umh", "uneven multi-hexagon search", AV_ME_METHOD_UMH, "me"),
226 { "mb_size", "macroblock size", OFFSET(mb_size), AV_OPT_TYPE_INT, {.i64 = 16}, 4, 16, FLAGS },
227 { "search_param", "search parameter", OFFSET(search_param), AV_OPT_TYPE_INT, {.i64 = 32}, 4, INT_MAX, FLAGS },
228 { "vsbmc", "variable-size block motion compensation", OFFSET(vsbmc), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS },
229 { "scd", "scene change detection method", OFFSET(scd_method), AV_OPT_TYPE_INT, {.i64 = SCD_METHOD_FDIFF}, SCD_METHOD_NONE, SCD_METHOD_FDIFF, FLAGS, .unit = "scene" },
230 CONST("none", "disable detection", SCD_METHOD_NONE, "scene"),
231 CONST("fdiff", "frame difference", SCD_METHOD_FDIFF, "scene"),
232 { "scd_threshold", "scene change threshold", OFFSET(scd_threshold), AV_OPT_TYPE_DOUBLE, {.dbl = 10.}, 0, 100.0, FLAGS },
233 { NULL }
234 };
235
236 AVFILTER_DEFINE_CLASS(minterpolate);
237
238 static const enum AVPixelFormat pix_fmts[] = {
239 AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P,
240 AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P,
241 AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P,
242 AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P,
243 AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P,
244 AV_PIX_FMT_YUVJ411P,
245 AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P,
246 AV_PIX_FMT_GRAY8,
247 AV_PIX_FMT_NONE
248 };
249
250 ✗ static uint64_t get_sbad(AVMotionEstContext *me_ctx, int x, int y, int x_mv, int y_mv)
251 {
252 ✗ uint8_t *data_cur = me_ctx->data_cur;
253 ✗ uint8_t *data_next = me_ctx->data_ref;
254 ✗ int linesize_cur = me_ctx->linesize_cur;
255 ✗ int linesize_next = me_ctx->linesize_ref;
256 ✗ int mv_x1 = x_mv - x;
257 ✗ int mv_y1 = y_mv - y;
258 int mv_x, mv_y, i, j;
259 ✗ uint64_t sbad = 0;
260
261 ✗ x = av_clip(x, me_ctx->x_min, me_ctx->x_max);
262 ✗ y = av_clip(y, me_ctx->y_min, me_ctx->y_max);
263 ✗ mv_x = av_clip(x_mv - x, -FFMIN(x - me_ctx->x_min, me_ctx->x_max - x), FFMIN(x - me_ctx->x_min, me_ctx->x_max - x));
264 ✗ mv_y = av_clip(y_mv - y, -FFMIN(y - me_ctx->y_min, me_ctx->y_max - y), FFMIN(y - me_ctx->y_min, me_ctx->y_max - y));
265
266 ✗ data_cur += (y + mv_y) * linesize_cur;
267 ✗ data_next += (y - mv_y) * linesize_next;
268
269 ✗ for (j = 0; j < me_ctx->mb_size; j++)
270 ✗ for (i = 0; i < me_ctx->mb_size; i++)
271 ✗ sbad += FFABS(data_cur[x + mv_x + i + j * linesize_cur] - data_next[x - mv_x + i + j * linesize_next]);
272
273 ✗ return sbad + (FFABS(mv_x1 - me_ctx->pred_x) + FFABS(mv_y1 - me_ctx->pred_y)) * COST_PRED_SCALE;
274 }
275
276 23392 static uint64_t get_sbad_ob(AVMotionEstContext *me_ctx, int x, int y, int x_mv, int y_mv)
277 {
278 23392 uint8_t *data_cur = me_ctx->data_cur;
279 23392 uint8_t *data_next = me_ctx->data_ref;
280 23392 int linesize_cur = me_ctx->linesize_cur;
281 23392 int linesize_next = me_ctx->linesize_ref;
282 23392 int x_min = me_ctx->x_min + me_ctx->mb_size / 2;
283 23392 int x_max = me_ctx->x_max - me_ctx->mb_size / 2;
284 23392 int y_min = me_ctx->y_min + me_ctx->mb_size / 2;
285 23392 int y_max = me_ctx->y_max - me_ctx->mb_size / 2;
286 23392 int mv_x1 = x_mv - x;
287 23392 int mv_y1 = y_mv - y;
288 int mv_x, mv_y, i, j;
289 23392 uint64_t sbad = 0;
290
291 23392 x = av_clip(x, x_min, x_max);
292 23392 y = av_clip(y, y_min, y_max);
293 23392 mv_x = av_clip(x_mv - x, -FFMIN(x - x_min, x_max - x), FFMIN(x - x_min, x_max - x));
294 23392 mv_y = av_clip(y_mv - y, -FFMIN(y - y_min, y_max - y), FFMIN(y - y_min, y_max - y));
295
296
2/2
✓ Branch 0 taken 748544 times.
✓ Branch 1 taken 23392 times.
771936 for (j = -me_ctx->mb_size / 2; j < me_ctx->mb_size * 3 / 2; j++)
297
2/2
✓ Branch 0 taken 23953408 times.
✓ Branch 1 taken 748544 times.
24701952 for (i = -me_ctx->mb_size / 2; i < me_ctx->mb_size * 3 / 2; i++)
298
2/2
✓ Branch 0 taken 22169924 times.
✓ Branch 1 taken 1783484 times.
23953408 sbad += FFABS(data_cur[x + mv_x + i + (y + mv_y + j) * linesize_cur] - data_next[x - mv_x + i + (y - mv_y + j) * linesize_next]);
299
300 23392 return sbad + (FFABS(mv_x1 - me_ctx->pred_x) + FFABS(mv_y1 - me_ctx->pred_y)) * COST_PRED_SCALE;
301 }
302
303 ✗ static uint64_t get_sad_ob(AVMotionEstContext *me_ctx, int x, int y, int x_mv, int y_mv)
304 {
305 ✗ uint8_t *data_ref = me_ctx->data_ref;
306 ✗ uint8_t *data_cur = me_ctx->data_cur;
307 ✗ int linesize_ref = me_ctx->linesize_ref;
308 ✗ int linesize_cur = me_ctx->linesize_cur;
309 ✗ int x_min = me_ctx->x_min + me_ctx->mb_size / 2;
310 ✗ int x_max = me_ctx->x_max - me_ctx->mb_size / 2;
311 ✗ int y_min = me_ctx->y_min + me_ctx->mb_size / 2;
312 ✗ int y_max = me_ctx->y_max - me_ctx->mb_size / 2;
313 ✗ int mv_x = x_mv - x;
314 ✗ int mv_y = y_mv - y;
315 int i, j;
316 ✗ uint64_t sad = 0;
317
318 ✗ x = av_clip(x, x_min, x_max);
319 ✗ y = av_clip(y, y_min, y_max);
320 ✗ x_mv = av_clip(x_mv, x_min, x_max);
321 ✗ y_mv = av_clip(y_mv, y_min, y_max);
322
323 ✗ for (j = -me_ctx->mb_size / 2; j < me_ctx->mb_size * 3 / 2; j++)
324 ✗ for (i = -me_ctx->mb_size / 2; i < me_ctx->mb_size * 3 / 2; i++)
325 ✗ sad += FFABS(data_ref[x_mv + i + (y_mv + j) * linesize_ref] - data_cur[x + i + (y + j) * linesize_cur]);
326
327 ✗ return sad + (FFABS(mv_x - me_ctx->pred_x) + FFABS(mv_y - me_ctx->pred_y)) * COST_PRED_SCALE;
328 }
329
330 2 static int config_input(AVFilterLink *inlink)
331 {
332 2 MIContext *mi_ctx = inlink->dst->priv;
333 2 AVMotionEstContext *me_ctx = &mi_ctx->me_ctx;
334 2 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
335 2 const int height = inlink->h;
336 2 const int width = inlink->w;
337 int i;
338
339 2 mi_ctx->log2_chroma_h = desc->log2_chroma_h;
340 2 mi_ctx->log2_chroma_w = desc->log2_chroma_w;
341 2 mi_ctx->bitdepth = desc->comp[0].depth;
342
343 2 mi_ctx->nb_planes = av_pix_fmt_count_planes(inlink->format);
344
345 2 mi_ctx->log2_mb_size = av_ceil_log2_c(mi_ctx->mb_size);
346 2 mi_ctx->mb_size = 1 << mi_ctx->log2_mb_size;
347
348 2 mi_ctx->b_width = width >> mi_ctx->log2_mb_size;
349 2 mi_ctx->b_height = height >> mi_ctx->log2_mb_size;
350 2 mi_ctx->b_count = mi_ctx->b_width * mi_ctx->b_height;
351
352
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (i = 0; i < NB_FRAMES; i++) {
353 8 Frame *frame = &mi_ctx->frames[i];
354 8 frame->blocks = av_calloc(mi_ctx->b_count, sizeof(*frame->blocks));
355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!frame->blocks)
356 ✗ return AVERROR(ENOMEM);
357 }
358
359
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (mi_ctx->mi_mode == MI_MODE_MCI) {
360
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (mi_ctx->b_width < 2 || mi_ctx->b_height < 2) {
361 ✗ av_log(inlink->dst, AV_LOG_ERROR, "Height or width < %d\n",
362 ✗ 2 * mi_ctx->mb_size);
363 ✗ return AVERROR(EINVAL);
364 }
365 2 ff_me_init_context(me_ctx, mi_ctx->mb_size, mi_ctx->search_param,
366 2 width, height, 0, (mi_ctx->b_width - 1) << mi_ctx->log2_mb_size,
367 2 0, (mi_ctx->b_height - 1) << mi_ctx->log2_mb_size);
368
369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (mi_ctx->me_mode == ME_MODE_BIDIR)
370 ✗ me_ctx->get_cost = &get_sad_ob;
371
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (mi_ctx->me_mode == ME_MODE_BILAT)
372 2 me_ctx->get_cost = &get_sbad_ob;
373
374 2 mi_ctx->pixel_mvs = av_calloc(width * height, sizeof(*mi_ctx->pixel_mvs));
375 2 mi_ctx->pixel_weights = av_calloc(width * height, sizeof(*mi_ctx->pixel_weights));
376 2 mi_ctx->pixel_refs = av_calloc(width * height, sizeof(*mi_ctx->pixel_refs));
377
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 if (!mi_ctx->pixel_mvs || !mi_ctx->pixel_weights || !mi_ctx->pixel_refs)
378 ✗ return AVERROR(ENOMEM);
379
380
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (mi_ctx->me_mode == ME_MODE_BILAT)
381
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!FF_ALLOCZ_TYPED_ARRAY(mi_ctx->int_blocks, mi_ctx->b_count))
382 ✗ return AVERROR(ENOMEM);
383
384
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (mi_ctx->me_method == AV_ME_METHOD_EPZS) {
385
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (i = 0; i < 3; i++) {
386 6 mi_ctx->mv_table[i] = av_calloc(mi_ctx->b_count, sizeof(*mi_ctx->mv_table[0]));
387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!mi_ctx->mv_table[i])
388 ✗ return AVERROR(ENOMEM);
389 }
390 }
391 }
392
393
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (mi_ctx->scd_method == SCD_METHOD_FDIFF) {
394 2 mi_ctx->sad = ff_scene_sad_get_fn(mi_ctx->bitdepth);
395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!mi_ctx->sad)
396 ✗ return AVERROR(EINVAL);
397 }
398
399 2 return 0;
400 }
401
402 2 static int config_output(AVFilterLink *outlink)
403 {
404 2 MIContext *mi_ctx = outlink->src->priv;
405 2 FilterLink *l = ff_filter_link(outlink);
406
407 2 l->frame_rate = mi_ctx->frame_rate;
408 2 outlink->time_base = av_inv_q(mi_ctx->frame_rate);
409
410 2 return 0;
411 }
412
413 #define ADD_PRED(preds, px, py)\
414 do {\
415 preds.mvs[preds.nb][0] = px;\
416 preds.mvs[preds.nb][1] = py;\
417 preds.nb++;\
418 } while(0)
419
420 1200 static void search_mv(MIContext *mi_ctx, Block *blocks, int mb_x, int mb_y, int dir)
421 {
422 1200 AVMotionEstContext *me_ctx = &mi_ctx->me_ctx;
423 1200 AVMotionEstPredictor *preds = me_ctx->preds;
424 1200 Block *block = &blocks[mb_x + mb_y * mi_ctx->b_width];
425
426 1200 const int x_mb = mb_x << mi_ctx->log2_mb_size;
427 1200 const int y_mb = mb_y << mi_ctx->log2_mb_size;
428 1200 const int mb_i = mb_x + mb_y * mi_ctx->b_width;
429 1200 int mv[2] = {x_mb, y_mb};
430
431
1/10
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1200 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1200 switch (mi_ctx->me_method) {
432 ✗ case AV_ME_METHOD_ESA:
433 ✗ ff_me_search_esa(me_ctx, x_mb, y_mb, mv);
434 ✗ break;
435 ✗ case AV_ME_METHOD_TSS:
436 ✗ ff_me_search_tss(me_ctx, x_mb, y_mb, mv);
437 ✗ break;
438 ✗ case AV_ME_METHOD_TDLS:
439 ✗ ff_me_search_tdls(me_ctx, x_mb, y_mb, mv);
440 ✗ break;
441 ✗ case AV_ME_METHOD_NTSS:
442 ✗ ff_me_search_ntss(me_ctx, x_mb, y_mb, mv);
443 ✗ break;
444 ✗ case AV_ME_METHOD_FSS:
445 ✗ ff_me_search_fss(me_ctx, x_mb, y_mb, mv);
446 ✗ break;
447 ✗ case AV_ME_METHOD_DS:
448 ✗ ff_me_search_ds(me_ctx, x_mb, y_mb, mv);
449 ✗ break;
450 ✗ case AV_ME_METHOD_HEXBS:
451 ✗ ff_me_search_hexbs(me_ctx, x_mb, y_mb, mv);
452 ✗ break;
453 1200 case AV_ME_METHOD_EPZS:
454
455 1200 preds[0].nb = 0;
456 1200 preds[1].nb = 0;
457
458 1200 ADD_PRED(preds[0], 0, 0);
459
460 //left mb in current frame
461
2/2
✓ Branch 0 taken 1140 times.
✓ Branch 1 taken 60 times.
1200 if (mb_x > 0)
462 1140 ADD_PRED(preds[0], mi_ctx->mv_table[0][mb_i - 1][dir][0], mi_ctx->mv_table[0][mb_i - 1][dir][1]);
463
464 //top mb in current frame
465
2/2
✓ Branch 0 taken 1120 times.
✓ Branch 1 taken 80 times.
1200 if (mb_y > 0)
466 1120 ADD_PRED(preds[0], mi_ctx->mv_table[0][mb_i - mi_ctx->b_width][dir][0], mi_ctx->mv_table[0][mb_i - mi_ctx->b_width][dir][1]);
467
468 //top-right mb in current frame
469
4/4
✓ Branch 0 taken 1120 times.
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 1064 times.
✓ Branch 3 taken 56 times.
1200 if (mb_y > 0 && mb_x + 1 < mi_ctx->b_width)
470 1064 ADD_PRED(preds[0], mi_ctx->mv_table[0][mb_i - mi_ctx->b_width + 1][dir][0], mi_ctx->mv_table[0][mb_i - mi_ctx->b_width + 1][dir][1]);
471
472 //median predictor
473
2/2
✓ Branch 0 taken 1008 times.
✓ Branch 1 taken 192 times.
1200 if (preds[0].nb == 4) {
474 1008 me_ctx->pred_x = mid_pred(preds[0].mvs[1][0], preds[0].mvs[2][0], preds[0].mvs[3][0]);
475 1008 me_ctx->pred_y = mid_pred(preds[0].mvs[1][1], preds[0].mvs[2][1], preds[0].mvs[3][1]);
476
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 80 times.
192 } else if (preds[0].nb == 3) {
477 112 me_ctx->pred_x = mid_pred(0, preds[0].mvs[1][0], preds[0].mvs[2][0]);
478 112 me_ctx->pred_y = mid_pred(0, preds[0].mvs[1][1], preds[0].mvs[2][1]);
479
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 4 times.
80 } else if (preds[0].nb == 2) {
480 76 me_ctx->pred_x = preds[0].mvs[1][0];
481 76 me_ctx->pred_y = preds[0].mvs[1][1];
482 } else {
483 4 me_ctx->pred_x = 0;
484 4 me_ctx->pred_y = 0;
485 }
486
487 //collocated mb in prev frame
488 1200 ADD_PRED(preds[0], mi_ctx->mv_table[1][mb_i][dir][0], mi_ctx->mv_table[1][mb_i][dir][1]);
489
490 //accelerator motion vector of collocated block in prev frame
491 1200 ADD_PRED(preds[1], mi_ctx->mv_table[1][mb_i][dir][0] + (mi_ctx->mv_table[1][mb_i][dir][0] - mi_ctx->mv_table[2][mb_i][dir][0]),
492 mi_ctx->mv_table[1][mb_i][dir][1] + (mi_ctx->mv_table[1][mb_i][dir][1] - mi_ctx->mv_table[2][mb_i][dir][1]));
493
494 //left mb in prev frame
495
2/2
✓ Branch 0 taken 1140 times.
✓ Branch 1 taken 60 times.
1200 if (mb_x > 0)
496 1140 ADD_PRED(preds[1], mi_ctx->mv_table[1][mb_i - 1][dir][0], mi_ctx->mv_table[1][mb_i - 1][dir][1]);
497
498 //top mb in prev frame
499
2/2
✓ Branch 0 taken 1120 times.
✓ Branch 1 taken 80 times.
1200 if (mb_y > 0)
500 1120 ADD_PRED(preds[1], mi_ctx->mv_table[1][mb_i - mi_ctx->b_width][dir][0], mi_ctx->mv_table[1][mb_i - mi_ctx->b_width][dir][1]);
501
502 //right mb in prev frame
503
2/2
✓ Branch 0 taken 1140 times.
✓ Branch 1 taken 60 times.
1200 if (mb_x + 1 < mi_ctx->b_width)
504 1140 ADD_PRED(preds[1], mi_ctx->mv_table[1][mb_i + 1][dir][0], mi_ctx->mv_table[1][mb_i + 1][dir][1]);
505
506 //bottom mb in prev frame
507
2/2
✓ Branch 0 taken 1120 times.
✓ Branch 1 taken 80 times.
1200 if (mb_y + 1 < mi_ctx->b_height)
508 1120 ADD_PRED(preds[1], mi_ctx->mv_table[1][mb_i + mi_ctx->b_width][dir][0], mi_ctx->mv_table[1][mb_i + mi_ctx->b_width][dir][1]);
509
510 1200 ff_me_search_epzs(me_ctx, x_mb, y_mb, mv);
511
512 1200 mi_ctx->mv_table[0][mb_i][dir][0] = mv[0] - x_mb;
513 1200 mi_ctx->mv_table[0][mb_i][dir][1] = mv[1] - y_mb;
514
515 1200 break;
516 ✗ case AV_ME_METHOD_UMH:
517
518 ✗ preds[0].nb = 0;
519
520 ✗ ADD_PRED(preds[0], 0, 0);
521
522 //left mb in current frame
523 ✗ if (mb_x > 0)
524 ✗ ADD_PRED(preds[0], blocks[mb_i - 1].mvs[dir][0], blocks[mb_i - 1].mvs[dir][1]);
525
526 ✗ if (mb_y > 0) {
527 //top mb in current frame
528 ✗ ADD_PRED(preds[0], blocks[mb_i - mi_ctx->b_width].mvs[dir][0], blocks[mb_i - mi_ctx->b_width].mvs[dir][1]);
529
530 //top-right mb in current frame
531 ✗ if (mb_x + 1 < mi_ctx->b_width)
532 ✗ ADD_PRED(preds[0], blocks[mb_i - mi_ctx->b_width + 1].mvs[dir][0], blocks[mb_i - mi_ctx->b_width + 1].mvs[dir][1]);
533 //top-left mb in current frame
534 ✗ else if (mb_x > 0)
535 ✗ ADD_PRED(preds[0], blocks[mb_i - mi_ctx->b_width - 1].mvs[dir][0], blocks[mb_i - mi_ctx->b_width - 1].mvs[dir][1]);
536 }
537
538 //median predictor
539 ✗ if (preds[0].nb == 4) {
540 ✗ me_ctx->pred_x = mid_pred(preds[0].mvs[1][0], preds[0].mvs[2][0], preds[0].mvs[3][0]);
541 ✗ me_ctx->pred_y = mid_pred(preds[0].mvs[1][1], preds[0].mvs[2][1], preds[0].mvs[3][1]);
542 ✗ } else if (preds[0].nb == 3) {
543 ✗ me_ctx->pred_x = mid_pred(0, preds[0].mvs[1][0], preds[0].mvs[2][0]);
544 ✗ me_ctx->pred_y = mid_pred(0, preds[0].mvs[1][1], preds[0].mvs[2][1]);
545 ✗ } else if (preds[0].nb == 2) {
546 ✗ me_ctx->pred_x = preds[0].mvs[1][0];
547 ✗ me_ctx->pred_y = preds[0].mvs[1][1];
548 } else {
549 ✗ me_ctx->pred_x = 0;
550 ✗ me_ctx->pred_y = 0;
551 }
552
553 ✗ ff_me_search_umh(me_ctx, x_mb, y_mb, mv);
554
555 ✗ break;
556 }
557
558 1200 block->mvs[dir][0] = mv[0] - x_mb;
559 1200 block->mvs[dir][1] = mv[1] - y_mb;
560 1200 }
561
562 4 static void bilateral_me(MIContext *mi_ctx)
563 {
564 Block *block;
565 int mb_x, mb_y;
566
567
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 4 times.
64 for (mb_y = 0; mb_y < mi_ctx->b_height; mb_y++)
568
2/2
✓ Branch 0 taken 1200 times.
✓ Branch 1 taken 60 times.
1260 for (mb_x = 0; mb_x < mi_ctx->b_width; mb_x++) {
569 1200 block = &mi_ctx->int_blocks[mb_x + mb_y * mi_ctx->b_width];
570
571 1200 block->cid = 0;
572 1200 block->sb = 0;
573
574 1200 block->mvs[0][0] = 0;
575 1200 block->mvs[0][1] = 0;
576 }
577
578
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 4 times.
64 for (mb_y = 0; mb_y < mi_ctx->b_height; mb_y++)
579
2/2
✓ Branch 0 taken 1200 times.
✓ Branch 1 taken 60 times.
1260 for (mb_x = 0; mb_x < mi_ctx->b_width; mb_x++)
580 1200 search_mv(mi_ctx, mi_ctx->int_blocks, mb_x, mb_y, 0);
581 4 }
582
583 ✗ static int var_size_bme(MIContext *mi_ctx, Block *block, int x_mb, int y_mb, int n)
584 {
585 ✗ AVMotionEstContext *me_ctx = &mi_ctx->me_ctx;
586 uint64_t cost_sb, cost_old;
587 ✗ int mb_size = me_ctx->mb_size;
588 ✗ int search_param = me_ctx->search_param;
589 int mv_x, mv_y;
590 int x, y;
591 int ret;
592
593 ✗ me_ctx->mb_size = 1 << n;
594 ✗ cost_old = me_ctx->get_cost(me_ctx, x_mb, y_mb, x_mb + block->mvs[0][0], y_mb + block->mvs[0][1]);
595 ✗ me_ctx->mb_size = mb_size;
596
597 ✗ if (!cost_old) {
598 ✗ block->sb = 0;
599 ✗ return 0;
600 }
601
602 ✗ if (!block->subs) {
603 ✗ block->subs = av_mallocz(4 * sizeof(*block->subs));
604 ✗ if (!block->subs)
605 ✗ return AVERROR(ENOMEM);
606 }
607
608 ✗ block->sb = 1;
609
610 ✗ for (y = 0; y < 2; y++)
611 ✗ for (x = 0; x < 2; x++) {
612 ✗ Block *sb = &block->subs[x + y * 2];
613 ✗ int mv[2] = {x_mb + block->mvs[0][0], y_mb + block->mvs[0][1]};
614
615 ✗ me_ctx->mb_size = 1 << (n - 1);
616 ✗ me_ctx->search_param = 2;
617 ✗ me_ctx->pred_x = block->mvs[0][0];
618 ✗ me_ctx->pred_y = block->mvs[0][1];
619
620 ✗ cost_sb = ff_me_search_ds(&mi_ctx->me_ctx, x_mb + block->mvs[0][0], y_mb + block->mvs[0][1], mv);
621 ✗ mv_x = mv[0] - x_mb;
622 ✗ mv_y = mv[1] - y_mb;
623
624 ✗ me_ctx->mb_size = mb_size;
625 ✗ me_ctx->search_param = search_param;
626
627 ✗ if (cost_sb < cost_old / 4) {
628 ✗ sb->mvs[0][0] = mv_x;
629 ✗ sb->mvs[0][1] = mv_y;
630
631 ✗ if (n > 1) {
632 ✗ if (ret = var_size_bme(mi_ctx, sb, x_mb + (x << (n - 1)), y_mb + (y << (n - 1)), n - 1))
633 ✗ return ret;
634 } else
635 ✗ sb->sb = 0;
636 } else {
637 ✗ block->sb = 0;
638 ✗ return 0;
639 }
640 }
641
642 ✗ return 0;
643 }
644
645 ✗ static int cluster_mvs(MIContext *mi_ctx)
646 {
647 ✗ int changed, c, c_max = 0;
648 int mb_x, mb_y, x, y;
649 int mv_x, mv_y, avg_x, avg_y, dx, dy;
650 int d, ret;
651 Block *block;
652 Cluster *cluster, *cluster_new;
653
654 do {
655 ✗ changed = 0;
656 ✗ for (mb_y = 0; mb_y < mi_ctx->b_height; mb_y++)
657 ✗ for (mb_x = 0; mb_x < mi_ctx->b_width; mb_x++) {
658 ✗ block = &mi_ctx->int_blocks[mb_x + mb_y * mi_ctx->b_width];
659 ✗ c = block->cid;
660 ✗ cluster = &mi_ctx->clusters[c];
661 ✗ mv_x = block->mvs[0][0];
662 ✗ mv_y = block->mvs[0][1];
663
664 ✗ if (cluster->nb < 2)
665 ✗ continue;
666
667 ✗ avg_x = cluster->sum[0] / cluster->nb;
668 ✗ avg_y = cluster->sum[1] / cluster->nb;
669 ✗ dx = avg_x - mv_x;
670 ✗ dy = avg_y - mv_y;
671
672 ✗ if (FFABS(dx) > CLUSTER_THRESHOLD || FFABS(dy) > CLUSTER_THRESHOLD) {
673
674 ✗ for (d = 1; d < 5; d++)
675 ✗ for (y = FFMAX(mb_y - d, 0); y < FFMIN(mb_y + d + 1, mi_ctx->b_height); y++)
676 ✗ for (x = FFMAX(mb_x - d, 0); x < FFMIN(mb_x + d + 1, mi_ctx->b_width); x++) {
677 ✗ Block *nb = &mi_ctx->int_blocks[x + y * mi_ctx->b_width];
678 ✗ if (nb->cid > block->cid) {
679 ✗ if (nb->cid < c || c == block->cid)
680 ✗ c = nb->cid;
681 }
682 }
683
684 ✗ if (c == block->cid)
685 ✗ c = c_max + 1;
686
687 ✗ if (c >= NB_CLUSTERS) {
688 ✗ continue;
689 }
690
691 ✗ cluster_new = &mi_ctx->clusters[c];
692 ✗ cluster_new->sum[0] += mv_x;
693 ✗ cluster_new->sum[1] += mv_y;
694 ✗ cluster->sum[0] -= mv_x;
695 ✗ cluster->sum[1] -= mv_y;
696 ✗ cluster_new->nb++;
697 ✗ cluster->nb--;
698
699 ✗ c_max = FFMAX(c_max, c);
700 ✗ block->cid = c;
701
702 ✗ changed = 1;
703 }
704 }
705 ✗ } while (changed);
706
707 /* find boundaries */
708 ✗ for (mb_y = 0; mb_y < mi_ctx->b_height; mb_y++)
709 ✗ for (mb_x = 0; mb_x < mi_ctx->b_width; mb_x++) {
710 ✗ block = &mi_ctx->int_blocks[mb_x + mb_y * mi_ctx->b_width];
711 ✗ for (y = FFMAX(mb_y - 1, 0); y < FFMIN(mb_y + 2, mi_ctx->b_height); y++)
712 ✗ for (x = FFMAX(mb_x - 1, 0); x < FFMIN(mb_x + 2, mi_ctx->b_width); x++) {
713 ✗ dx = x - mb_x;
714 ✗ dy = y - mb_y;
715
716 ✗ if ((x - mb_x) && (y - mb_y) || !dx && !dy)
717 ✗ continue;
718
719 ✗ if (!mb_x || !mb_y || mb_x == mi_ctx->b_width - 1 || mb_y == mi_ctx->b_height - 1)
720 ✗ continue;
721
722 ✗ if (block->cid != mi_ctx->int_blocks[x + y * mi_ctx->b_width].cid) {
723 ✗ if (!dx && block->cid == mi_ctx->int_blocks[x + (mb_y - dy) * mi_ctx->b_width].cid ||
724 ✗ !dy && block->cid == mi_ctx->int_blocks[(mb_x - dx) + y * mi_ctx->b_width].cid) {
725 ✗ if (ret = var_size_bme(mi_ctx, block, mb_x << mi_ctx->log2_mb_size, mb_y << mi_ctx->log2_mb_size, mi_ctx->log2_mb_size))
726 ✗ return ret;
727 }
728 }
729 }
730 }
731
732 ✗ return 0;
733 }
734
735 10 static int inject_frame(AVFilterLink *inlink, AVFrame *avf_in)
736 {
737 10 AVFilterContext *ctx = inlink->dst;
738 10 MIContext *mi_ctx = ctx->priv;
739 Frame frame_tmp;
740 int mb_x, mb_y, dir;
741
742 10 av_frame_free(&mi_ctx->frames[0].avf);
743 10 frame_tmp = mi_ctx->frames[0];
744 10 memmove(&mi_ctx->frames[0], &mi_ctx->frames[1], sizeof(mi_ctx->frames[0]) * (NB_FRAMES - 1));
745 10 mi_ctx->frames[NB_FRAMES - 1] = frame_tmp;
746 10 mi_ctx->frames[NB_FRAMES - 1].avf = avf_in;
747
748
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (mi_ctx->mi_mode == MI_MODE_MCI) {
749
750
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (mi_ctx->me_method == AV_ME_METHOD_EPZS) {
751 10 mi_ctx->mv_table[2] = memcpy(mi_ctx->mv_table[2], mi_ctx->mv_table[1], sizeof(*mi_ctx->mv_table[1]) * mi_ctx->b_count);
752 10 mi_ctx->mv_table[1] = memcpy(mi_ctx->mv_table[1], mi_ctx->mv_table[0], sizeof(*mi_ctx->mv_table[0]) * mi_ctx->b_count);
753 }
754
755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (mi_ctx->me_mode == ME_MODE_BIDIR) {
756
757 ✗ if (mi_ctx->frames[1].avf) {
758 ✗ for (dir = 0; dir < 2; dir++) {
759 ✗ mi_ctx->me_ctx.linesize_cur = mi_ctx->frames[2].avf->linesize[0];
760 ✗ mi_ctx->me_ctx.linesize_ref = mi_ctx->frames[dir ? 3 : 1].avf->linesize[0];
761 ✗ mi_ctx->me_ctx.data_cur = mi_ctx->frames[2].avf->data[0];
762 ✗ mi_ctx->me_ctx.data_ref = mi_ctx->frames[dir ? 3 : 1].avf->data[0];
763
764 ✗ for (mb_y = 0; mb_y < mi_ctx->b_height; mb_y++)
765 ✗ for (mb_x = 0; mb_x < mi_ctx->b_width; mb_x++)
766 ✗ search_mv(mi_ctx, mi_ctx->frames[2].blocks, mb_x, mb_y, dir);
767 }
768 }
769
770
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 } else if (mi_ctx->me_mode == ME_MODE_BILAT) {
771 Block *block;
772 int i, ret;
773
774
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
10 if (!mi_ctx->frames[0].avf)
775 6 return 0;
776
777 4 mi_ctx->me_ctx.linesize_cur = mi_ctx->frames[1].avf->linesize[0];
778 4 mi_ctx->me_ctx.linesize_ref = mi_ctx->frames[2].avf->linesize[0];
779 4 mi_ctx->me_ctx.data_cur = mi_ctx->frames[1].avf->data[0];
780 4 mi_ctx->me_ctx.data_ref = mi_ctx->frames[2].avf->data[0];
781
782 4 bilateral_me(mi_ctx);
783
784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (mi_ctx->mc_mode == MC_MODE_AOBMC) {
785
786 ✗ for (mb_y = 0; mb_y < mi_ctx->b_height; mb_y++)
787 ✗ for (mb_x = 0; mb_x < mi_ctx->b_width; mb_x++) {
788 ✗ int x_mb = mb_x << mi_ctx->log2_mb_size;
789 ✗ int y_mb = mb_y << mi_ctx->log2_mb_size;
790 ✗ block = &mi_ctx->int_blocks[mb_x + mb_y * mi_ctx->b_width];
791
792 ✗ block->sbad = get_sbad(&mi_ctx->me_ctx, x_mb, y_mb, x_mb + block->mvs[0][0], y_mb + block->mvs[0][1]);
793 }
794 }
795
796
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (mi_ctx->vsbmc) {
797
798 ✗ for (i = 0; i < NB_CLUSTERS; i++) {
799 ✗ mi_ctx->clusters[i].sum[0] = 0;
800 ✗ mi_ctx->clusters[i].sum[1] = 0;
801 ✗ mi_ctx->clusters[i].nb = 0;
802 }
803
804 ✗ for (mb_y = 0; mb_y < mi_ctx->b_height; mb_y++)
805 ✗ for (mb_x = 0; mb_x < mi_ctx->b_width; mb_x++) {
806 ✗ block = &mi_ctx->int_blocks[mb_x + mb_y * mi_ctx->b_width];
807
808 ✗ mi_ctx->clusters[0].sum[0] += block->mvs[0][0];
809 ✗ mi_ctx->clusters[0].sum[1] += block->mvs[0][1];
810 }
811
812 ✗ mi_ctx->clusters[0].nb = mi_ctx->b_count;
813
814 ✗ if (ret = cluster_mvs(mi_ctx))
815 ✗ return ret;
816 }
817 }
818 }
819
820 4 return 0;
821 }
822
823 4 static int detect_scene_change(AVFilterContext *ctx)
824 {
825 4 MIContext *mi_ctx = ctx->priv;
826 4 AVFilterLink *input = ctx->inputs[0];
827 4 uint8_t *p1 = mi_ctx->frames[1].avf->data[0];
828 4 ptrdiff_t linesize1 = mi_ctx->frames[1].avf->linesize[0];
829 4 uint8_t *p2 = mi_ctx->frames[2].avf->data[0];
830 4 ptrdiff_t linesize2 = mi_ctx->frames[2].avf->linesize[0];
831
832
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (mi_ctx->scd_method == SCD_METHOD_FDIFF) {
833 4 double ret = 0, mafd, diff;
834 uint64_t sad;
835 4 mi_ctx->sad(p1, linesize1, p2, linesize2, input->w, input->h, &sad);
836 4 mafd = (double) sad * 100.0 / (input->h * input->w) / (1 << mi_ctx->bitdepth);
837 4 diff = fabs(mafd - mi_ctx->prev_mafd);
838
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 ret = av_clipf(FFMIN(mafd, diff), 0, 100.0);
839 4 mi_ctx->prev_mafd = mafd;
840
841 4 return ret >= mi_ctx->scd_threshold;
842 }
843
844 ✗ return 0;
845 }
846
847 #define ADD_PIXELS(b_weight, mv_x, mv_y)\
848 do {\
849 if (!b_weight || pixel_refs->nb + 1 >= NB_PIXEL_MVS)\
850 continue;\
851 pixel_refs->refs[pixel_refs->nb] = 1;\
852 pixel_weights->weights[pixel_refs->nb] = b_weight * (ALPHA_MAX - alpha);\
853 pixel_mvs->mvs[pixel_refs->nb][0] = av_clip((mv_x * alpha) / ALPHA_MAX, x_min, x_max);\
854 pixel_mvs->mvs[pixel_refs->nb][1] = av_clip((mv_y * alpha) / ALPHA_MAX, y_min, y_max);\
855 pixel_refs->nb++;\
856 pixel_refs->refs[pixel_refs->nb] = 2;\
857 pixel_weights->weights[pixel_refs->nb] = b_weight * alpha;\
858 pixel_mvs->mvs[pixel_refs->nb][0] = av_clip(-mv_x * (ALPHA_MAX - alpha) / ALPHA_MAX, x_min, x_max);\
859 pixel_mvs->mvs[pixel_refs->nb][1] = av_clip(-mv_y * (ALPHA_MAX - alpha) / ALPHA_MAX, y_min, y_max);\
860 pixel_refs->nb++;\
861 } while(0)
862
863 ✗ static void bidirectional_obmc(MIContext *mi_ctx, int alpha)
864 {
865 int x, y;
866 ✗ int width = mi_ctx->frames[0].avf->width;
867 ✗ int height = mi_ctx->frames[0].avf->height;
868 int mb_y, mb_x, dir;
869
870 ✗ for (y = 0; y < height; y++)
871 ✗ for (x = 0; x < width; x++)
872 ✗ mi_ctx->pixel_refs[x + y * width].nb = 0;
873
874 ✗ for (dir = 0; dir < 2; dir++)
875 ✗ for (mb_y = 0; mb_y < mi_ctx->b_height; mb_y++)
876 ✗ for (mb_x = 0; mb_x < mi_ctx->b_width; mb_x++) {
877 ✗ int a = dir ? alpha : (ALPHA_MAX - alpha);
878 ✗ int mv_x = mi_ctx->frames[2 - dir].blocks[mb_x + mb_y * mi_ctx->b_width].mvs[dir][0];
879 ✗ int mv_y = mi_ctx->frames[2 - dir].blocks[mb_x + mb_y * mi_ctx->b_width].mvs[dir][1];
880 int start_x, start_y;
881 int startc_x, startc_y, endc_x, endc_y;
882
883 ✗ start_x = (mb_x << mi_ctx->log2_mb_size) - mi_ctx->mb_size / 2 + mv_x * a / ALPHA_MAX;
884 ✗ start_y = (mb_y << mi_ctx->log2_mb_size) - mi_ctx->mb_size / 2 + mv_y * a / ALPHA_MAX;
885
886 ✗ startc_x = av_clip(start_x, 0, width - 1);
887 ✗ startc_y = av_clip(start_y, 0, height - 1);
888 ✗ endc_x = av_clip(start_x + (2 << mi_ctx->log2_mb_size), 0, width - 1);
889 ✗ endc_y = av_clip(start_y + (2 << mi_ctx->log2_mb_size), 0, height - 1);
890
891 ✗ if (dir) {
892 ✗ mv_x = -mv_x;
893 ✗ mv_y = -mv_y;
894 }
895
896 ✗ for (y = startc_y; y < endc_y; y++) {
897 ✗ int y_min = -y;
898 ✗ int y_max = height - y - 1;
899 ✗ for (x = startc_x; x < endc_x; x++) {
900 ✗ int x_min = -x;
901 ✗ int x_max = width - x - 1;
902 ✗ int obmc_weight = obmc_tab_linear[4 - mi_ctx->log2_mb_size][(x - start_x) + ((y - start_y) << (mi_ctx->log2_mb_size + 1))];
903 ✗ PixelMVS *pixel_mvs = &mi_ctx->pixel_mvs[x + y * width];
904 ✗ PixelWeights *pixel_weights = &mi_ctx->pixel_weights[x + y * width];
905 ✗ PixelRefs *pixel_refs = &mi_ctx->pixel_refs[x + y * width];
906
907 ✗ ADD_PIXELS(obmc_weight, mv_x, mv_y);
908 }
909 }
910 }
911 ✗ }
912
913 8 static void set_frame_data(MIContext *mi_ctx, int alpha, AVFrame *avf_out)
914 {
915 int x, y, plane;
916
917
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8 times.
32 for (plane = 0; plane < mi_ctx->nb_planes; plane++) {
918 24 int width = avf_out->width;
919 24 int height = avf_out->height;
920
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 8 times.
24 int chroma = plane == 1 || plane == 2;
921
922
2/2
✓ Branch 0 taken 5760 times.
✓ Branch 1 taken 24 times.
5784 for (y = 0; y < height; y++)
923
2/2
✓ Branch 0 taken 1843200 times.
✓ Branch 1 taken 5760 times.
1848960 for (x = 0; x < width; x++) {
924 int x_mv, y_mv;
925 1843200 int weight_sum = 0;
926 1843200 int i, val = 0;
927 1843200 PixelMVS *pixel_mvs = &mi_ctx->pixel_mvs[x + y * width];
928 1843200 PixelWeights *pixel_weights = &mi_ctx->pixel_weights[x + y * width];
929 1843200 PixelRefs *pixel_refs = &mi_ctx->pixel_refs[x + y * width];
930
931
2/2
✓ Branch 0 taken 13505936 times.
✓ Branch 1 taken 1843200 times.
15349136 for (i = 0; i < pixel_refs->nb; i++)
932 13505936 weight_sum += pixel_weights->weights[i];
933
934
3/4
✓ Branch 0 taken 1838728 times.
✓ Branch 1 taken 4472 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1838728 times.
1843200 if (!weight_sum || !pixel_refs->nb) {
935 4472 pixel_weights->weights[0] = ALPHA_MAX - alpha;
936 4472 pixel_refs->refs[0] = 1;
937 4472 pixel_mvs->mvs[0][0] = 0;
938 4472 pixel_mvs->mvs[0][1] = 0;
939 4472 pixel_weights->weights[1] = alpha;
940 4472 pixel_refs->refs[1] = 2;
941 4472 pixel_mvs->mvs[1][0] = 0;
942 4472 pixel_mvs->mvs[1][1] = 0;
943 4472 pixel_refs->nb = 2;
944
945 4472 weight_sum = ALPHA_MAX;
946 }
947
948
2/2
✓ Branch 0 taken 1228800 times.
✓ Branch 1 taken 614400 times.
1843200 if (chroma) {
949
2/2
✓ Branch 0 taken 9009920 times.
✓ Branch 1 taken 1228800 times.
10238720 for (i = 0; i < pixel_refs->nb; i++) {
950 9009920 Frame *frame = &mi_ctx->frames[pixel_refs->refs[i]];
951 9009920 x_mv = (x >> mi_ctx->log2_chroma_w) + pixel_mvs->mvs[i][0] / (1 << mi_ctx->log2_chroma_w);
952 9009920 y_mv = (y >> mi_ctx->log2_chroma_h) + pixel_mvs->mvs[i][1] / (1 << mi_ctx->log2_chroma_h);
953 9009920 val += pixel_weights->weights[i] * frame->avf->data[plane][x_mv + y_mv * frame->avf->linesize[plane]];
954 }
955 } else {
956
2/2
✓ Branch 0 taken 4504960 times.
✓ Branch 1 taken 614400 times.
5119360 for (i = 0; i < pixel_refs->nb; i++) {
957 4504960 Frame *frame = &mi_ctx->frames[pixel_refs->refs[i]];
958 4504960 x_mv = x + pixel_mvs->mvs[i][0];
959 4504960 y_mv = y + pixel_mvs->mvs[i][1];
960 4504960 val += pixel_weights->weights[i] * frame->avf->data[plane][x_mv + y_mv * frame->avf->linesize[plane]];
961 }
962 }
963
964
1/2
✓ Branch 0 taken 1843200 times.
✗ Branch 1 not taken.
1843200 val = ROUNDED_DIV(val, weight_sum);
965
966
2/2
✓ Branch 0 taken 1228800 times.
✓ Branch 1 taken 614400 times.
1843200 if (chroma)
967 1228800 avf_out->data[plane][(x >> mi_ctx->log2_chroma_w) + (y >> mi_ctx->log2_chroma_h) * avf_out->linesize[plane]] = val;
968 else
969 614400 avf_out->data[plane][x + y * avf_out->linesize[plane]] = val;
970 }
971 }
972 8 }
973
974 ✗ static void var_size_bmc(MIContext *mi_ctx, Block *block, int x_mb, int y_mb, int n, int alpha)
975 {
976 int sb_x, sb_y;
977 ✗ int width = mi_ctx->frames[0].avf->width;
978 ✗ int height = mi_ctx->frames[0].avf->height;
979
980 ✗ for (sb_y = 0; sb_y < 2; sb_y++)
981 ✗ for (sb_x = 0; sb_x < 2; sb_x++) {
982 ✗ Block *sb = &block->subs[sb_x + sb_y * 2];
983
984 ✗ if (sb->sb)
985 ✗ var_size_bmc(mi_ctx, sb, x_mb + (sb_x << (n - 1)), y_mb + (sb_y << (n - 1)), n - 1, alpha);
986 else {
987 int x, y;
988 ✗ int mv_x = sb->mvs[0][0] * 2;
989 ✗ int mv_y = sb->mvs[0][1] * 2;
990
991 ✗ int start_x = x_mb + (sb_x << (n - 1));
992 ✗ int start_y = y_mb + (sb_y << (n - 1));
993 ✗ int end_x = start_x + (1 << (n - 1));
994 ✗ int end_y = start_y + (1 << (n - 1));
995
996 ✗ for (y = start_y; y < end_y; y++) {
997 ✗ int y_min = -y;
998 ✗ int y_max = height - y - 1;
999 ✗ for (x = start_x; x < end_x; x++) {
1000 ✗ int x_min = -x;
1001 ✗ int x_max = width - x - 1;
1002 ✗ PixelMVS *pixel_mvs = &mi_ctx->pixel_mvs[x + y * width];
1003 ✗ PixelWeights *pixel_weights = &mi_ctx->pixel_weights[x + y * width];
1004 ✗ PixelRefs *pixel_refs = &mi_ctx->pixel_refs[x + y * width];
1005
1006 ✗ ADD_PIXELS(PX_WEIGHT_MAX, mv_x, mv_y);
1007 }
1008 }
1009 }
1010 }
1011 ✗ }
1012
1013 2400 static void bilateral_obmc(MIContext *mi_ctx, Block *block, int mb_x, int mb_y, int alpha)
1014 {
1015 int x, y;
1016 2400 int width = mi_ctx->frames[0].avf->width;
1017 2400 int height = mi_ctx->frames[0].avf->height;
1018
1019 Block *nb;
1020 int nb_x, nb_y;
1021 uint64_t sbads[9];
1022
1023 2400 int mv_x = block->mvs[0][0] * 2;
1024 2400 int mv_y = block->mvs[0][1] * 2;
1025 int start_x, start_y;
1026 int startc_x, startc_y, endc_x, endc_y;
1027
1028
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2400 times.
2400 if (mi_ctx->mc_mode == MC_MODE_AOBMC)
1029 ✗ for (nb_y = FFMAX(0, mb_y - 1); nb_y < FFMIN(mb_y + 2, mi_ctx->b_height); nb_y++)
1030 ✗ for (nb_x = FFMAX(0, mb_x - 1); nb_x < FFMIN(mb_x + 2, mi_ctx->b_width); nb_x++) {
1031 ✗ int x_nb = nb_x << mi_ctx->log2_mb_size;
1032 ✗ int y_nb = nb_y << mi_ctx->log2_mb_size;
1033
1034 ✗ if (nb_x - mb_x || nb_y - mb_y)
1035 ✗ sbads[nb_x - mb_x + 1 + (nb_y - mb_y + 1) * 3] = get_sbad(&mi_ctx->me_ctx, x_nb, y_nb, x_nb + block->mvs[0][0], y_nb + block->mvs[0][1]);
1036 }
1037
1038 2400 start_x = (mb_x << mi_ctx->log2_mb_size) - mi_ctx->mb_size / 2;
1039 2400 start_y = (mb_y << mi_ctx->log2_mb_size) - mi_ctx->mb_size / 2;
1040
1041 2400 startc_x = av_clip(start_x, 0, width - 1);
1042 2400 startc_y = av_clip(start_y, 0, height - 1);
1043 2400 endc_x = av_clip(start_x + (2 << mi_ctx->log2_mb_size), 0, width - 1);
1044 2400 endc_y = av_clip(start_y + (2 << mi_ctx->log2_mb_size), 0, height - 1);
1045
1046
2/2
✓ Branch 0 taken 74080 times.
✓ Branch 1 taken 2400 times.
76480 for (y = startc_y; y < endc_y; y++) {
1047 74080 int y_min = -y;
1048 74080 int y_max = height - y - 1;
1049
2/2
✓ Branch 0 taken 2307592 times.
✓ Branch 1 taken 74080 times.
2381672 for (x = startc_x; x < endc_x; x++) {
1050 2307592 int x_min = -x;
1051 2307592 int x_max = width - x - 1;
1052 2307592 int obmc_weight = obmc_tab_linear[4 - mi_ctx->log2_mb_size][(x - start_x) + ((y - start_y) << (mi_ctx->log2_mb_size + 1))];
1053 2307592 PixelMVS *pixel_mvs = &mi_ctx->pixel_mvs[x + y * width];
1054 2307592 PixelWeights *pixel_weights = &mi_ctx->pixel_weights[x + y * width];
1055 2307592 PixelRefs *pixel_refs = &mi_ctx->pixel_refs[x + y * width];
1056
1057
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2307592 times.
2307592 if (mi_ctx->mc_mode == MC_MODE_AOBMC) {
1058 ✗ nb_x = (((x - start_x) >> (mi_ctx->log2_mb_size - 1)) * 2 - 3) / 2;
1059 ✗ nb_y = (((y - start_y) >> (mi_ctx->log2_mb_size - 1)) * 2 - 3) / 2;
1060
1061 ✗ if ((nb_x || nb_y) && mb_x + nb_x < mi_ctx->b_width && mb_y + nb_y < mi_ctx->b_height) {
1062 ✗ uint64_t sbad = sbads[nb_x + 1 + (nb_y + 1) * 3];
1063 ✗ nb = &mi_ctx->int_blocks[mb_x + nb_x + (mb_y + nb_y) * mi_ctx->b_width];
1064
1065 ✗ if (sbad && sbad != UINT64_MAX && nb->sbad != UINT64_MAX) {
1066 ✗ int phi = av_clip(ALPHA_MAX * nb->sbad / sbad, 0, ALPHA_MAX);
1067 ✗ obmc_weight = obmc_weight * phi / ALPHA_MAX;
1068 }
1069 }
1070 }
1071
1072
3/4
✓ Branch 0 taken 2248008 times.
✓ Branch 1 taken 59584 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2248008 times.
2307592 ADD_PIXELS(obmc_weight, mv_x, mv_y);
1073 }
1074 }
1075 2400 }
1076
1077 13 static void interpolate(AVFilterLink *inlink, AVFrame *avf_out)
1078 {
1079 13 AVFilterContext *ctx = inlink->dst;
1080 13 AVFilterLink *outlink = ctx->outputs[0];
1081 13 MIContext *mi_ctx = ctx->priv;
1082 int x, y;
1083 int plane, alpha;
1084 int64_t pts;
1085
1086 13 pts = av_rescale(avf_out->pts, (int64_t) ALPHA_MAX * outlink->time_base.num * inlink->time_base.den,
1087 13 (int64_t) outlink->time_base.den * inlink->time_base.num);
1088
1089
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (mi_ctx->frames[2].avf->pts > mi_ctx->frames[1].avf->pts) {
1090 13 alpha = (pts - mi_ctx->frames[1].avf->pts * ALPHA_MAX) / (mi_ctx->frames[2].avf->pts - mi_ctx->frames[1].avf->pts);
1091 13 alpha = av_clip(alpha, 0, ALPHA_MAX);
1092 } else {
1093 ✗ av_log(ctx, AV_LOG_DEBUG, "duplicate input PTS detected\n");
1094 ✗ alpha = 0;
1095 }
1096
1097
4/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 8 times.
13 if (alpha == 0 || alpha == ALPHA_MAX) {
1098
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 av_frame_copy(avf_out, alpha ? mi_ctx->frames[2].avf : mi_ctx->frames[1].avf);
1099 5 return;
1100 }
1101
1102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (mi_ctx->scene_changed) {
1103 ✗ av_log(ctx, AV_LOG_DEBUG, "scene changed, input pts %"PRId64"\n", mi_ctx->frames[1].avf->pts);
1104 /* duplicate frame */
1105 ✗ av_frame_copy(avf_out, alpha > ALPHA_MAX / 2 ? mi_ctx->frames[2].avf : mi_ctx->frames[1].avf);
1106 ✗ return;
1107 }
1108
1109
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 switch(mi_ctx->mi_mode) {
1110 ✗ case MI_MODE_DUP:
1111 ✗ av_frame_copy(avf_out, alpha > ALPHA_MAX / 2 ? mi_ctx->frames[2].avf : mi_ctx->frames[1].avf);
1112
1113 ✗ break;
1114 ✗ case MI_MODE_BLEND:
1115 ✗ for (plane = 0; plane < mi_ctx->nb_planes; plane++) {
1116 ✗ int width = avf_out->width;
1117 ✗ int height = avf_out->height;
1118
1119 ✗ if (plane == 1 || plane == 2) {
1120 ✗ width = AV_CEIL_RSHIFT(width, mi_ctx->log2_chroma_w);
1121 ✗ height = AV_CEIL_RSHIFT(height, mi_ctx->log2_chroma_h);
1122 }
1123
1124 ✗ for (y = 0; y < height; y++) {
1125 ✗ for (x = 0; x < width; x++) {
1126 ✗ avf_out->data[plane][x + y * avf_out->linesize[plane]] =
1127 ✗ (alpha * mi_ctx->frames[2].avf->data[plane][x + y * mi_ctx->frames[2].avf->linesize[plane]] +
1128 ✗ (ALPHA_MAX - alpha) * mi_ctx->frames[1].avf->data[plane][x + y * mi_ctx->frames[1].avf->linesize[plane]] + 512) >> 10;
1129 }
1130 }
1131 }
1132
1133 ✗ break;
1134 8 case MI_MODE_MCI:
1135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (mi_ctx->me_mode == ME_MODE_BIDIR) {
1136 ✗ bidirectional_obmc(mi_ctx, alpha);
1137 ✗ set_frame_data(mi_ctx, alpha, avf_out);
1138
1139
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 } else if (mi_ctx->me_mode == ME_MODE_BILAT) {
1140 int mb_x, mb_y;
1141 Block *block;
1142
1143
2/2
✓ Branch 0 taken 1920 times.
✓ Branch 1 taken 8 times.
1928 for (y = 0; y < mi_ctx->frames[0].avf->height; y++)
1144
2/2
✓ Branch 0 taken 614400 times.
✓ Branch 1 taken 1920 times.
616320 for (x = 0; x < mi_ctx->frames[0].avf->width; x++)
1145 614400 mi_ctx->pixel_refs[x + y * mi_ctx->frames[0].avf->width].nb = 0;
1146
1147
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 8 times.
128 for (mb_y = 0; mb_y < mi_ctx->b_height; mb_y++)
1148
2/2
✓ Branch 0 taken 2400 times.
✓ Branch 1 taken 120 times.
2520 for (mb_x = 0; mb_x < mi_ctx->b_width; mb_x++) {
1149 2400 block = &mi_ctx->int_blocks[mb_x + mb_y * mi_ctx->b_width];
1150
1151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2400 times.
2400 if (block->sb)
1152 ✗ var_size_bmc(mi_ctx, block, mb_x << mi_ctx->log2_mb_size, mb_y << mi_ctx->log2_mb_size, mi_ctx->log2_mb_size, alpha);
1153
1154 2400 bilateral_obmc(mi_ctx, block, mb_x, mb_y, alpha);
1155
1156 }
1157
1158 8 set_frame_data(mi_ctx, alpha, avf_out);
1159 }
1160
1161 8 break;
1162 }
1163 }
1164
1165 8 static int filter_frame(AVFilterLink *inlink, AVFrame *avf_in)
1166 {
1167 8 AVFilterContext *ctx = inlink->dst;
1168 8 AVFilterLink *outlink = ctx->outputs[0];
1169 8 MIContext *mi_ctx = ctx->priv;
1170 int ret;
1171
1172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (avf_in->pts == AV_NOPTS_VALUE) {
1173 ✗ ret = ff_filter_frame(ctx->outputs[0], avf_in);
1174 ✗ return ret;
1175 }
1176
1177
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
8 if (!mi_ctx->frames[NB_FRAMES - 1].avf || avf_in->pts < mi_ctx->frames[NB_FRAMES - 1].avf->pts) {
1178 2 av_log(ctx, AV_LOG_VERBOSE, "Initializing out pts from input pts %"PRId64"\n", avf_in->pts);
1179 2 mi_ctx->out_pts = av_rescale_q(avf_in->pts, inlink->time_base, outlink->time_base);
1180 }
1181
1182
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 if (!mi_ctx->frames[NB_FRAMES - 1].avf)
1183
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (ret = inject_frame(inlink, av_frame_clone(avf_in)))
1184 ✗ return ret;
1185
1186
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (ret = inject_frame(inlink, avf_in))
1187 ✗ return ret;
1188
1189
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (!mi_ctx->frames[0].avf)
1190 4 return 0;
1191
1192 4 mi_ctx->scene_changed = detect_scene_change(ctx);
1193
1194 13 for (;;) {
1195 AVFrame *avf_out;
1196
1197
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 13 times.
17 if (av_compare_ts(mi_ctx->out_pts, outlink->time_base, mi_ctx->frames[2].avf->pts, inlink->time_base) > 0)
1198 4 break;
1199
1200
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 if (!(avf_out = ff_get_video_buffer(ctx->outputs[0], inlink->w, inlink->h)))
1201 ✗ return AVERROR(ENOMEM);
1202
1203 13 av_frame_copy_props(avf_out, mi_ctx->frames[NB_FRAMES - 1].avf);
1204 13 avf_out->pts = mi_ctx->out_pts++;
1205 13 avf_out->duration = 1;
1206
1207 13 interpolate(inlink, avf_out);
1208
1209
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 if ((ret = ff_filter_frame(ctx->outputs[0], avf_out)) < 0)
1210 ✗ return ret;
1211 }
1212
1213 4 return 0;
1214 }
1215
1216 600 static av_cold void free_blocks(Block *block)
1217 {
1218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 600 times.
600 if (block->subs)
1219 ✗ for (int i = 0; i < 4; i++)
1220 ✗ free_blocks(&block->subs[i]);
1221 600 av_freep(&block->subs);
1222 600 }
1223
1224 4 static av_cold void uninit(AVFilterContext *ctx)
1225 {
1226 4 MIContext *mi_ctx = ctx->priv;
1227 int i, m;
1228
1229 4 av_freep(&mi_ctx->pixel_mvs);
1230 4 av_freep(&mi_ctx->pixel_weights);
1231 4 av_freep(&mi_ctx->pixel_refs);
1232
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (mi_ctx->int_blocks)
1233
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 2 times.
602 for (m = 0; m < mi_ctx->b_count; m++)
1234 600 free_blocks(&mi_ctx->int_blocks[m]);
1235 4 av_freep(&mi_ctx->int_blocks);
1236
1237
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (i = 0; i < NB_FRAMES; i++) {
1238 16 Frame *frame = &mi_ctx->frames[i];
1239 16 av_freep(&frame->blocks);
1240 16 av_frame_free(&frame->avf);
1241 }
1242
1243
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
16 for (i = 0; i < 3; i++)
1244 12 av_freep(&mi_ctx->mv_table[i]);
1245 4 }
1246
1247 static const AVFilterPad minterpolate_inputs[] = {
1248 {
1249 .name = "default",
1250 .type = AVMEDIA_TYPE_VIDEO,
1251 .filter_frame = filter_frame,
1252 .config_props = config_input,
1253 },
1254 };
1255
1256 static const AVFilterPad minterpolate_outputs[] = {
1257 {
1258 .name = "default",
1259 .type = AVMEDIA_TYPE_VIDEO,
1260 .config_props = config_output,
1261 },
1262 };
1263
1264 const FFFilter ff_vf_minterpolate = {
1265 .p.name = "minterpolate",
1266 .p.description = NULL_IF_CONFIG_SMALL("Frame rate conversion using Motion Interpolation."),
1267 .p.priv_class = &minterpolate_class,
1268 .priv_size = sizeof(MIContext),
1269 .uninit = uninit,
1270 FILTER_INPUTS(minterpolate_inputs),
1271 FILTER_OUTPUTS(minterpolate_outputs),
1272 FILTER_PIXFMTS_ARRAY(pix_fmts),
1273 };
1274