FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavfilter/vf_minterpolate.c
Date: 2026-09-26 05:01:43
Exec Total Coverage
Lines: 300 615 48.8%
Functions: 13 19 68.4%
Branches: 144 402 35.8%

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 = me_ctx->linesize;
255 ✗ int mv_x1 = x_mv - x;
256 ✗ int mv_y1 = y_mv - y;
257 int mv_x, mv_y, i, j;
258 ✗ uint64_t sbad = 0;
259
260 ✗ x = av_clip(x, me_ctx->x_min, me_ctx->x_max);
261 ✗ y = av_clip(y, me_ctx->y_min, me_ctx->y_max);
262 ✗ 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));
263 ✗ 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));
264
265 ✗ data_cur += (y + mv_y) * linesize;
266 ✗ data_next += (y - mv_y) * linesize;
267
268 ✗ for (j = 0; j < me_ctx->mb_size; j++)
269 ✗ for (i = 0; i < me_ctx->mb_size; i++)
270 ✗ sbad += FFABS(data_cur[x + mv_x + i + j * linesize] - data_next[x - mv_x + i + j * linesize]);
271
272 ✗ return sbad + (FFABS(mv_x1 - me_ctx->pred_x) + FFABS(mv_y1 - me_ctx->pred_y)) * COST_PRED_SCALE;
273 }
274
275 23392 static uint64_t get_sbad_ob(AVMotionEstContext *me_ctx, int x, int y, int x_mv, int y_mv)
276 {
277 23392 uint8_t *data_cur = me_ctx->data_cur;
278 23392 uint8_t *data_next = me_ctx->data_ref;
279 23392 int linesize = me_ctx->linesize;
280 23392 int x_min = me_ctx->x_min + me_ctx->mb_size / 2;
281 23392 int x_max = me_ctx->x_max - me_ctx->mb_size / 2;
282 23392 int y_min = me_ctx->y_min + me_ctx->mb_size / 2;
283 23392 int y_max = me_ctx->y_max - me_ctx->mb_size / 2;
284 23392 int mv_x1 = x_mv - x;
285 23392 int mv_y1 = y_mv - y;
286 int mv_x, mv_y, i, j;
287 23392 uint64_t sbad = 0;
288
289 23392 x = av_clip(x, x_min, x_max);
290 23392 y = av_clip(y, y_min, y_max);
291 23392 mv_x = av_clip(x_mv - x, -FFMIN(x - x_min, x_max - x), FFMIN(x - x_min, x_max - x));
292 23392 mv_y = av_clip(y_mv - y, -FFMIN(y - y_min, y_max - y), FFMIN(y - y_min, y_max - y));
293
294
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++)
295
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++)
296
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] - data_next[x - mv_x + i + (y - mv_y + j) * linesize]);
297
298 23392 return sbad + (FFABS(mv_x1 - me_ctx->pred_x) + FFABS(mv_y1 - me_ctx->pred_y)) * COST_PRED_SCALE;
299 }
300
301 ✗ static uint64_t get_sad_ob(AVMotionEstContext *me_ctx, int x, int y, int x_mv, int y_mv)
302 {
303 ✗ uint8_t *data_ref = me_ctx->data_ref;
304 ✗ uint8_t *data_cur = me_ctx->data_cur;
305 ✗ int linesize = me_ctx->linesize;
306 ✗ int x_min = me_ctx->x_min + me_ctx->mb_size / 2;
307 ✗ int x_max = me_ctx->x_max - me_ctx->mb_size / 2;
308 ✗ int y_min = me_ctx->y_min + me_ctx->mb_size / 2;
309 ✗ int y_max = me_ctx->y_max - me_ctx->mb_size / 2;
310 ✗ int mv_x = x_mv - x;
311 ✗ int mv_y = y_mv - y;
312 int i, j;
313 ✗ uint64_t sad = 0;
314
315 ✗ x = av_clip(x, x_min, x_max);
316 ✗ y = av_clip(y, y_min, y_max);
317 ✗ x_mv = av_clip(x_mv, x_min, x_max);
318 ✗ y_mv = av_clip(y_mv, y_min, y_max);
319
320 ✗ for (j = -me_ctx->mb_size / 2; j < me_ctx->mb_size * 3 / 2; j++)
321 ✗ for (i = -me_ctx->mb_size / 2; i < me_ctx->mb_size * 3 / 2; i++)
322 ✗ sad += FFABS(data_ref[x_mv + i + (y_mv + j) * linesize] - data_cur[x + i + (y + j) * linesize]);
323
324 ✗ return sad + (FFABS(mv_x - me_ctx->pred_x) + FFABS(mv_y - me_ctx->pred_y)) * COST_PRED_SCALE;
325 }
326
327 2 static int config_input(AVFilterLink *inlink)
328 {
329 2 MIContext *mi_ctx = inlink->dst->priv;
330 2 AVMotionEstContext *me_ctx = &mi_ctx->me_ctx;
331 2 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
332 2 const int height = inlink->h;
333 2 const int width = inlink->w;
334 int i;
335
336 2 mi_ctx->log2_chroma_h = desc->log2_chroma_h;
337 2 mi_ctx->log2_chroma_w = desc->log2_chroma_w;
338 2 mi_ctx->bitdepth = desc->comp[0].depth;
339
340 2 mi_ctx->nb_planes = av_pix_fmt_count_planes(inlink->format);
341
342 2 mi_ctx->log2_mb_size = av_ceil_log2_c(mi_ctx->mb_size);
343 2 mi_ctx->mb_size = 1 << mi_ctx->log2_mb_size;
344
345 2 mi_ctx->b_width = width >> mi_ctx->log2_mb_size;
346 2 mi_ctx->b_height = height >> mi_ctx->log2_mb_size;
347 2 mi_ctx->b_count = mi_ctx->b_width * mi_ctx->b_height;
348
349
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (i = 0; i < NB_FRAMES; i++) {
350 8 Frame *frame = &mi_ctx->frames[i];
351 8 frame->blocks = av_calloc(mi_ctx->b_count, sizeof(*frame->blocks));
352
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!frame->blocks)
353 ✗ return AVERROR(ENOMEM);
354 }
355
356
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (mi_ctx->mi_mode == MI_MODE_MCI) {
357
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) {
358 ✗ av_log(inlink->dst, AV_LOG_ERROR, "Height or width < %d\n",
359 ✗ 2 * mi_ctx->mb_size);
360 ✗ return AVERROR(EINVAL);
361 }
362 2 ff_me_init_context(me_ctx, mi_ctx->mb_size, mi_ctx->search_param,
363 2 width, height, 0, (mi_ctx->b_width - 1) << mi_ctx->log2_mb_size,
364 2 0, (mi_ctx->b_height - 1) << mi_ctx->log2_mb_size);
365
366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (mi_ctx->me_mode == ME_MODE_BIDIR)
367 ✗ me_ctx->get_cost = &get_sad_ob;
368
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (mi_ctx->me_mode == ME_MODE_BILAT)
369 2 me_ctx->get_cost = &get_sbad_ob;
370
371 2 mi_ctx->pixel_mvs = av_calloc(width * height, sizeof(*mi_ctx->pixel_mvs));
372 2 mi_ctx->pixel_weights = av_calloc(width * height, sizeof(*mi_ctx->pixel_weights));
373 2 mi_ctx->pixel_refs = av_calloc(width * height, sizeof(*mi_ctx->pixel_refs));
374
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)
375 ✗ return AVERROR(ENOMEM);
376
377
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (mi_ctx->me_mode == ME_MODE_BILAT)
378
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))
379 ✗ return AVERROR(ENOMEM);
380
381
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (mi_ctx->me_method == AV_ME_METHOD_EPZS) {
382
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (i = 0; i < 3; i++) {
383 6 mi_ctx->mv_table[i] = av_calloc(mi_ctx->b_count, sizeof(*mi_ctx->mv_table[0]));
384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!mi_ctx->mv_table[i])
385 ✗ return AVERROR(ENOMEM);
386 }
387 }
388 }
389
390
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (mi_ctx->scd_method == SCD_METHOD_FDIFF) {
391 2 mi_ctx->sad = ff_scene_sad_get_fn(mi_ctx->bitdepth);
392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!mi_ctx->sad)
393 ✗ return AVERROR(EINVAL);
394 }
395
396 2 return 0;
397 }
398
399 2 static int config_output(AVFilterLink *outlink)
400 {
401 2 MIContext *mi_ctx = outlink->src->priv;
402 2 FilterLink *l = ff_filter_link(outlink);
403
404 2 l->frame_rate = mi_ctx->frame_rate;
405 2 outlink->time_base = av_inv_q(mi_ctx->frame_rate);
406
407 2 return 0;
408 }
409
410 #define ADD_PRED(preds, px, py)\
411 do {\
412 preds.mvs[preds.nb][0] = px;\
413 preds.mvs[preds.nb][1] = py;\
414 preds.nb++;\
415 } while(0)
416
417 1200 static void search_mv(MIContext *mi_ctx, Block *blocks, int mb_x, int mb_y, int dir)
418 {
419 1200 AVMotionEstContext *me_ctx = &mi_ctx->me_ctx;
420 1200 AVMotionEstPredictor *preds = me_ctx->preds;
421 1200 Block *block = &blocks[mb_x + mb_y * mi_ctx->b_width];
422
423 1200 const int x_mb = mb_x << mi_ctx->log2_mb_size;
424 1200 const int y_mb = mb_y << mi_ctx->log2_mb_size;
425 1200 const int mb_i = mb_x + mb_y * mi_ctx->b_width;
426 1200 int mv[2] = {x_mb, y_mb};
427
428
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) {
429 ✗ case AV_ME_METHOD_ESA:
430 ✗ ff_me_search_esa(me_ctx, x_mb, y_mb, mv);
431 ✗ break;
432 ✗ case AV_ME_METHOD_TSS:
433 ✗ ff_me_search_tss(me_ctx, x_mb, y_mb, mv);
434 ✗ break;
435 ✗ case AV_ME_METHOD_TDLS:
436 ✗ ff_me_search_tdls(me_ctx, x_mb, y_mb, mv);
437 ✗ break;
438 ✗ case AV_ME_METHOD_NTSS:
439 ✗ ff_me_search_ntss(me_ctx, x_mb, y_mb, mv);
440 ✗ break;
441 ✗ case AV_ME_METHOD_FSS:
442 ✗ ff_me_search_fss(me_ctx, x_mb, y_mb, mv);
443 ✗ break;
444 ✗ case AV_ME_METHOD_DS:
445 ✗ ff_me_search_ds(me_ctx, x_mb, y_mb, mv);
446 ✗ break;
447 ✗ case AV_ME_METHOD_HEXBS:
448 ✗ ff_me_search_hexbs(me_ctx, x_mb, y_mb, mv);
449 ✗ break;
450 1200 case AV_ME_METHOD_EPZS:
451
452 1200 preds[0].nb = 0;
453 1200 preds[1].nb = 0;
454
455 1200 ADD_PRED(preds[0], 0, 0);
456
457 //left mb in current frame
458
2/2
✓ Branch 0 taken 1140 times.
✓ Branch 1 taken 60 times.
1200 if (mb_x > 0)
459 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]);
460
461 //top mb in current frame
462
2/2
✓ Branch 0 taken 1120 times.
✓ Branch 1 taken 80 times.
1200 if (mb_y > 0)
463 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]);
464
465 //top-right mb in current frame
466
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)
467 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]);
468
469 //median predictor
470
2/2
✓ Branch 0 taken 1008 times.
✓ Branch 1 taken 192 times.
1200 if (preds[0].nb == 4) {
471 1008 me_ctx->pred_x = mid_pred(preds[0].mvs[1][0], preds[0].mvs[2][0], preds[0].mvs[3][0]);
472 1008 me_ctx->pred_y = mid_pred(preds[0].mvs[1][1], preds[0].mvs[2][1], preds[0].mvs[3][1]);
473
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 80 times.
192 } else if (preds[0].nb == 3) {
474 112 me_ctx->pred_x = mid_pred(0, preds[0].mvs[1][0], preds[0].mvs[2][0]);
475 112 me_ctx->pred_y = mid_pred(0, preds[0].mvs[1][1], preds[0].mvs[2][1]);
476
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 4 times.
80 } else if (preds[0].nb == 2) {
477 76 me_ctx->pred_x = preds[0].mvs[1][0];
478 76 me_ctx->pred_y = preds[0].mvs[1][1];
479 } else {
480 4 me_ctx->pred_x = 0;
481 4 me_ctx->pred_y = 0;
482 }
483
484 //collocated mb in prev frame
485 1200 ADD_PRED(preds[0], mi_ctx->mv_table[1][mb_i][dir][0], mi_ctx->mv_table[1][mb_i][dir][1]);
486
487 //accelerator motion vector of collocated block in prev frame
488 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]),
489 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]));
490
491 //left mb in prev frame
492
2/2
✓ Branch 0 taken 1140 times.
✓ Branch 1 taken 60 times.
1200 if (mb_x > 0)
493 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]);
494
495 //top mb in prev frame
496
2/2
✓ Branch 0 taken 1120 times.
✓ Branch 1 taken 80 times.
1200 if (mb_y > 0)
497 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]);
498
499 //right mb in prev frame
500
2/2
✓ Branch 0 taken 1140 times.
✓ Branch 1 taken 60 times.
1200 if (mb_x + 1 < mi_ctx->b_width)
501 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]);
502
503 //bottom mb in prev frame
504
2/2
✓ Branch 0 taken 1120 times.
✓ Branch 1 taken 80 times.
1200 if (mb_y + 1 < mi_ctx->b_height)
505 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]);
506
507 1200 ff_me_search_epzs(me_ctx, x_mb, y_mb, mv);
508
509 1200 mi_ctx->mv_table[0][mb_i][dir][0] = mv[0] - x_mb;
510 1200 mi_ctx->mv_table[0][mb_i][dir][1] = mv[1] - y_mb;
511
512 1200 break;
513 ✗ case AV_ME_METHOD_UMH:
514
515 ✗ preds[0].nb = 0;
516
517 ✗ ADD_PRED(preds[0], 0, 0);
518
519 //left mb in current frame
520 ✗ if (mb_x > 0)
521 ✗ ADD_PRED(preds[0], blocks[mb_i - 1].mvs[dir][0], blocks[mb_i - 1].mvs[dir][1]);
522
523 ✗ if (mb_y > 0) {
524 //top mb in current frame
525 ✗ ADD_PRED(preds[0], blocks[mb_i - mi_ctx->b_width].mvs[dir][0], blocks[mb_i - mi_ctx->b_width].mvs[dir][1]);
526
527 //top-right mb in current frame
528 ✗ if (mb_x + 1 < mi_ctx->b_width)
529 ✗ 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]);
530 //top-left mb in current frame
531 ✗ else if (mb_x > 0)
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 }
534
535 //median predictor
536 ✗ if (preds[0].nb == 4) {
537 ✗ me_ctx->pred_x = mid_pred(preds[0].mvs[1][0], preds[0].mvs[2][0], preds[0].mvs[3][0]);
538 ✗ me_ctx->pred_y = mid_pred(preds[0].mvs[1][1], preds[0].mvs[2][1], preds[0].mvs[3][1]);
539 ✗ } else if (preds[0].nb == 3) {
540 ✗ me_ctx->pred_x = mid_pred(0, preds[0].mvs[1][0], preds[0].mvs[2][0]);
541 ✗ me_ctx->pred_y = mid_pred(0, preds[0].mvs[1][1], preds[0].mvs[2][1]);
542 ✗ } else if (preds[0].nb == 2) {
543 ✗ me_ctx->pred_x = preds[0].mvs[1][0];
544 ✗ me_ctx->pred_y = preds[0].mvs[1][1];
545 } else {
546 ✗ me_ctx->pred_x = 0;
547 ✗ me_ctx->pred_y = 0;
548 }
549
550 ✗ ff_me_search_umh(me_ctx, x_mb, y_mb, mv);
551
552 ✗ break;
553 }
554
555 1200 block->mvs[dir][0] = mv[0] - x_mb;
556 1200 block->mvs[dir][1] = mv[1] - y_mb;
557 1200 }
558
559 4 static void bilateral_me(MIContext *mi_ctx)
560 {
561 Block *block;
562 int mb_x, mb_y;
563
564
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++)
565
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++) {
566 1200 block = &mi_ctx->int_blocks[mb_x + mb_y * mi_ctx->b_width];
567
568 1200 block->cid = 0;
569 1200 block->sb = 0;
570
571 1200 block->mvs[0][0] = 0;
572 1200 block->mvs[0][1] = 0;
573 }
574
575
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++)
576
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++)
577 1200 search_mv(mi_ctx, mi_ctx->int_blocks, mb_x, mb_y, 0);
578 4 }
579
580 ✗ static int var_size_bme(MIContext *mi_ctx, Block *block, int x_mb, int y_mb, int n)
581 {
582 ✗ AVMotionEstContext *me_ctx = &mi_ctx->me_ctx;
583 uint64_t cost_sb, cost_old;
584 ✗ int mb_size = me_ctx->mb_size;
585 ✗ int search_param = me_ctx->search_param;
586 int mv_x, mv_y;
587 int x, y;
588 int ret;
589
590 ✗ me_ctx->mb_size = 1 << n;
591 ✗ cost_old = me_ctx->get_cost(me_ctx, x_mb, y_mb, x_mb + block->mvs[0][0], y_mb + block->mvs[0][1]);
592 ✗ me_ctx->mb_size = mb_size;
593
594 ✗ if (!cost_old) {
595 ✗ block->sb = 0;
596 ✗ return 0;
597 }
598
599 ✗ if (!block->subs) {
600 ✗ block->subs = av_mallocz(4 * sizeof(*block->subs));
601 ✗ if (!block->subs)
602 ✗ return AVERROR(ENOMEM);
603 }
604
605 ✗ block->sb = 1;
606
607 ✗ for (y = 0; y < 2; y++)
608 ✗ for (x = 0; x < 2; x++) {
609 ✗ Block *sb = &block->subs[x + y * 2];
610 ✗ int mv[2] = {x_mb + block->mvs[0][0], y_mb + block->mvs[0][1]};
611
612 ✗ me_ctx->mb_size = 1 << (n - 1);
613 ✗ me_ctx->search_param = 2;
614 ✗ me_ctx->pred_x = block->mvs[0][0];
615 ✗ me_ctx->pred_y = block->mvs[0][1];
616
617 ✗ cost_sb = ff_me_search_ds(&mi_ctx->me_ctx, x_mb + block->mvs[0][0], y_mb + block->mvs[0][1], mv);
618 ✗ mv_x = mv[0] - x_mb;
619 ✗ mv_y = mv[1] - y_mb;
620
621 ✗ me_ctx->mb_size = mb_size;
622 ✗ me_ctx->search_param = search_param;
623
624 ✗ if (cost_sb < cost_old / 4) {
625 ✗ sb->mvs[0][0] = mv_x;
626 ✗ sb->mvs[0][1] = mv_y;
627
628 ✗ if (n > 1) {
629 ✗ if (ret = var_size_bme(mi_ctx, sb, x_mb + (x << (n - 1)), y_mb + (y << (n - 1)), n - 1))
630 ✗ return ret;
631 } else
632 ✗ sb->sb = 0;
633 } else {
634 ✗ block->sb = 0;
635 ✗ return 0;
636 }
637 }
638
639 ✗ return 0;
640 }
641
642 ✗ static int cluster_mvs(MIContext *mi_ctx)
643 {
644 ✗ int changed, c, c_max = 0;
645 int mb_x, mb_y, x, y;
646 int mv_x, mv_y, avg_x, avg_y, dx, dy;
647 int d, ret;
648 Block *block;
649 Cluster *cluster, *cluster_new;
650
651 do {
652 ✗ changed = 0;
653 ✗ for (mb_y = 0; mb_y < mi_ctx->b_height; mb_y++)
654 ✗ for (mb_x = 0; mb_x < mi_ctx->b_width; mb_x++) {
655 ✗ block = &mi_ctx->int_blocks[mb_x + mb_y * mi_ctx->b_width];
656 ✗ c = block->cid;
657 ✗ cluster = &mi_ctx->clusters[c];
658 ✗ mv_x = block->mvs[0][0];
659 ✗ mv_y = block->mvs[0][1];
660
661 ✗ if (cluster->nb < 2)
662 ✗ continue;
663
664 ✗ avg_x = cluster->sum[0] / cluster->nb;
665 ✗ avg_y = cluster->sum[1] / cluster->nb;
666 ✗ dx = avg_x - mv_x;
667 ✗ dy = avg_y - mv_y;
668
669 ✗ if (FFABS(dx) > CLUSTER_THRESHOLD || FFABS(dy) > CLUSTER_THRESHOLD) {
670
671 ✗ for (d = 1; d < 5; d++)
672 ✗ for (y = FFMAX(mb_y - d, 0); y < FFMIN(mb_y + d + 1, mi_ctx->b_height); y++)
673 ✗ for (x = FFMAX(mb_x - d, 0); x < FFMIN(mb_x + d + 1, mi_ctx->b_width); x++) {
674 ✗ Block *nb = &mi_ctx->int_blocks[x + y * mi_ctx->b_width];
675 ✗ if (nb->cid > block->cid) {
676 ✗ if (nb->cid < c || c == block->cid)
677 ✗ c = nb->cid;
678 }
679 }
680
681 ✗ if (c == block->cid)
682 ✗ c = c_max + 1;
683
684 ✗ if (c >= NB_CLUSTERS) {
685 ✗ continue;
686 }
687
688 ✗ cluster_new = &mi_ctx->clusters[c];
689 ✗ cluster_new->sum[0] += mv_x;
690 ✗ cluster_new->sum[1] += mv_y;
691 ✗ cluster->sum[0] -= mv_x;
692 ✗ cluster->sum[1] -= mv_y;
693 ✗ cluster_new->nb++;
694 ✗ cluster->nb--;
695
696 ✗ c_max = FFMAX(c_max, c);
697 ✗ block->cid = c;
698
699 ✗ changed = 1;
700 }
701 }
702 ✗ } while (changed);
703
704 /* find boundaries */
705 ✗ for (mb_y = 0; mb_y < mi_ctx->b_height; mb_y++)
706 ✗ for (mb_x = 0; mb_x < mi_ctx->b_width; mb_x++) {
707 ✗ block = &mi_ctx->int_blocks[mb_x + mb_y * mi_ctx->b_width];
708 ✗ for (y = FFMAX(mb_y - 1, 0); y < FFMIN(mb_y + 2, mi_ctx->b_height); y++)
709 ✗ for (x = FFMAX(mb_x - 1, 0); x < FFMIN(mb_x + 2, mi_ctx->b_width); x++) {
710 ✗ dx = x - mb_x;
711 ✗ dy = y - mb_y;
712
713 ✗ if ((x - mb_x) && (y - mb_y) || !dx && !dy)
714 ✗ continue;
715
716 ✗ if (!mb_x || !mb_y || mb_x == mi_ctx->b_width - 1 || mb_y == mi_ctx->b_height - 1)
717 ✗ continue;
718
719 ✗ if (block->cid != mi_ctx->int_blocks[x + y * mi_ctx->b_width].cid) {
720 ✗ if (!dx && block->cid == mi_ctx->int_blocks[x + (mb_y - dy) * mi_ctx->b_width].cid ||
721 ✗ !dy && block->cid == mi_ctx->int_blocks[(mb_x - dx) + y * mi_ctx->b_width].cid) {
722 ✗ 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))
723 ✗ return ret;
724 }
725 }
726 }
727 }
728
729 ✗ return 0;
730 }
731
732 10 static int inject_frame(AVFilterLink *inlink, AVFrame *avf_in)
733 {
734 10 AVFilterContext *ctx = inlink->dst;
735 10 MIContext *mi_ctx = ctx->priv;
736 Frame frame_tmp;
737 int mb_x, mb_y, dir;
738
739 10 av_frame_free(&mi_ctx->frames[0].avf);
740 10 frame_tmp = mi_ctx->frames[0];
741 10 memmove(&mi_ctx->frames[0], &mi_ctx->frames[1], sizeof(mi_ctx->frames[0]) * (NB_FRAMES - 1));
742 10 mi_ctx->frames[NB_FRAMES - 1] = frame_tmp;
743 10 mi_ctx->frames[NB_FRAMES - 1].avf = avf_in;
744
745
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (mi_ctx->mi_mode == MI_MODE_MCI) {
746
747
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (mi_ctx->me_method == AV_ME_METHOD_EPZS) {
748 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);
749 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);
750 }
751
752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (mi_ctx->me_mode == ME_MODE_BIDIR) {
753
754 ✗ if (mi_ctx->frames[1].avf) {
755 ✗ for (dir = 0; dir < 2; dir++) {
756 ✗ mi_ctx->me_ctx.linesize = mi_ctx->frames[2].avf->linesize[0];
757 ✗ mi_ctx->me_ctx.data_cur = mi_ctx->frames[2].avf->data[0];
758 ✗ mi_ctx->me_ctx.data_ref = mi_ctx->frames[dir ? 3 : 1].avf->data[0];
759
760 ✗ for (mb_y = 0; mb_y < mi_ctx->b_height; mb_y++)
761 ✗ for (mb_x = 0; mb_x < mi_ctx->b_width; mb_x++)
762 ✗ search_mv(mi_ctx, mi_ctx->frames[2].blocks, mb_x, mb_y, dir);
763 }
764 }
765
766
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 } else if (mi_ctx->me_mode == ME_MODE_BILAT) {
767 Block *block;
768 int i, ret;
769
770
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
10 if (!mi_ctx->frames[0].avf)
771 6 return 0;
772
773 4 mi_ctx->me_ctx.linesize = mi_ctx->frames[0].avf->linesize[0];
774 4 mi_ctx->me_ctx.data_cur = mi_ctx->frames[1].avf->data[0];
775 4 mi_ctx->me_ctx.data_ref = mi_ctx->frames[2].avf->data[0];
776
777 4 bilateral_me(mi_ctx);
778
779
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (mi_ctx->mc_mode == MC_MODE_AOBMC) {
780
781 ✗ for (mb_y = 0; mb_y < mi_ctx->b_height; mb_y++)
782 ✗ for (mb_x = 0; mb_x < mi_ctx->b_width; mb_x++) {
783 ✗ int x_mb = mb_x << mi_ctx->log2_mb_size;
784 ✗ int y_mb = mb_y << mi_ctx->log2_mb_size;
785 ✗ block = &mi_ctx->int_blocks[mb_x + mb_y * mi_ctx->b_width];
786
787 ✗ block->sbad = get_sbad(&mi_ctx->me_ctx, x_mb, y_mb, x_mb + block->mvs[0][0], y_mb + block->mvs[0][1]);
788 }
789 }
790
791
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (mi_ctx->vsbmc) {
792
793 ✗ for (i = 0; i < NB_CLUSTERS; i++) {
794 ✗ mi_ctx->clusters[i].sum[0] = 0;
795 ✗ mi_ctx->clusters[i].sum[1] = 0;
796 ✗ mi_ctx->clusters[i].nb = 0;
797 }
798
799 ✗ for (mb_y = 0; mb_y < mi_ctx->b_height; mb_y++)
800 ✗ for (mb_x = 0; mb_x < mi_ctx->b_width; mb_x++) {
801 ✗ block = &mi_ctx->int_blocks[mb_x + mb_y * mi_ctx->b_width];
802
803 ✗ mi_ctx->clusters[0].sum[0] += block->mvs[0][0];
804 ✗ mi_ctx->clusters[0].sum[1] += block->mvs[0][1];
805 }
806
807 ✗ mi_ctx->clusters[0].nb = mi_ctx->b_count;
808
809 ✗ if (ret = cluster_mvs(mi_ctx))
810 ✗ return ret;
811 }
812 }
813 }
814
815 4 return 0;
816 }
817
818 4 static int detect_scene_change(AVFilterContext *ctx)
819 {
820 4 MIContext *mi_ctx = ctx->priv;
821 4 AVFilterLink *input = ctx->inputs[0];
822 4 uint8_t *p1 = mi_ctx->frames[1].avf->data[0];
823 4 ptrdiff_t linesize1 = mi_ctx->frames[1].avf->linesize[0];
824 4 uint8_t *p2 = mi_ctx->frames[2].avf->data[0];
825 4 ptrdiff_t linesize2 = mi_ctx->frames[2].avf->linesize[0];
826
827
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (mi_ctx->scd_method == SCD_METHOD_FDIFF) {
828 4 double ret = 0, mafd, diff;
829 uint64_t sad;
830 4 mi_ctx->sad(p1, linesize1, p2, linesize2, input->w, input->h, &sad);
831 4 mafd = (double) sad * 100.0 / (input->h * input->w) / (1 << mi_ctx->bitdepth);
832 4 diff = fabs(mafd - mi_ctx->prev_mafd);
833
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 ret = av_clipf(FFMIN(mafd, diff), 0, 100.0);
834 4 mi_ctx->prev_mafd = mafd;
835
836 4 return ret >= mi_ctx->scd_threshold;
837 }
838
839 ✗ return 0;
840 }
841
842 #define ADD_PIXELS(b_weight, mv_x, mv_y)\
843 do {\
844 if (!b_weight || pixel_refs->nb + 1 >= NB_PIXEL_MVS)\
845 continue;\
846 pixel_refs->refs[pixel_refs->nb] = 1;\
847 pixel_weights->weights[pixel_refs->nb] = b_weight * (ALPHA_MAX - alpha);\
848 pixel_mvs->mvs[pixel_refs->nb][0] = av_clip((mv_x * alpha) / ALPHA_MAX, x_min, x_max);\
849 pixel_mvs->mvs[pixel_refs->nb][1] = av_clip((mv_y * alpha) / ALPHA_MAX, y_min, y_max);\
850 pixel_refs->nb++;\
851 pixel_refs->refs[pixel_refs->nb] = 2;\
852 pixel_weights->weights[pixel_refs->nb] = b_weight * alpha;\
853 pixel_mvs->mvs[pixel_refs->nb][0] = av_clip(-mv_x * (ALPHA_MAX - alpha) / ALPHA_MAX, x_min, x_max);\
854 pixel_mvs->mvs[pixel_refs->nb][1] = av_clip(-mv_y * (ALPHA_MAX - alpha) / ALPHA_MAX, y_min, y_max);\
855 pixel_refs->nb++;\
856 } while(0)
857
858 ✗ static void bidirectional_obmc(MIContext *mi_ctx, int alpha)
859 {
860 int x, y;
861 ✗ int width = mi_ctx->frames[0].avf->width;
862 ✗ int height = mi_ctx->frames[0].avf->height;
863 int mb_y, mb_x, dir;
864
865 ✗ for (y = 0; y < height; y++)
866 ✗ for (x = 0; x < width; x++)
867 ✗ mi_ctx->pixel_refs[x + y * width].nb = 0;
868
869 ✗ for (dir = 0; dir < 2; dir++)
870 ✗ for (mb_y = 0; mb_y < mi_ctx->b_height; mb_y++)
871 ✗ for (mb_x = 0; mb_x < mi_ctx->b_width; mb_x++) {
872 ✗ int a = dir ? alpha : (ALPHA_MAX - alpha);
873 ✗ int mv_x = mi_ctx->frames[2 - dir].blocks[mb_x + mb_y * mi_ctx->b_width].mvs[dir][0];
874 ✗ int mv_y = mi_ctx->frames[2 - dir].blocks[mb_x + mb_y * mi_ctx->b_width].mvs[dir][1];
875 int start_x, start_y;
876 int startc_x, startc_y, endc_x, endc_y;
877
878 ✗ start_x = (mb_x << mi_ctx->log2_mb_size) - mi_ctx->mb_size / 2 + mv_x * a / ALPHA_MAX;
879 ✗ start_y = (mb_y << mi_ctx->log2_mb_size) - mi_ctx->mb_size / 2 + mv_y * a / ALPHA_MAX;
880
881 ✗ startc_x = av_clip(start_x, 0, width - 1);
882 ✗ startc_y = av_clip(start_y, 0, height - 1);
883 ✗ endc_x = av_clip(start_x + (2 << mi_ctx->log2_mb_size), 0, width - 1);
884 ✗ endc_y = av_clip(start_y + (2 << mi_ctx->log2_mb_size), 0, height - 1);
885
886 ✗ if (dir) {
887 ✗ mv_x = -mv_x;
888 ✗ mv_y = -mv_y;
889 }
890
891 ✗ for (y = startc_y; y < endc_y; y++) {
892 ✗ int y_min = -y;
893 ✗ int y_max = height - y - 1;
894 ✗ for (x = startc_x; x < endc_x; x++) {
895 ✗ int x_min = -x;
896 ✗ int x_max = width - x - 1;
897 ✗ int obmc_weight = obmc_tab_linear[4 - mi_ctx->log2_mb_size][(x - start_x) + ((y - start_y) << (mi_ctx->log2_mb_size + 1))];
898 ✗ PixelMVS *pixel_mvs = &mi_ctx->pixel_mvs[x + y * width];
899 ✗ PixelWeights *pixel_weights = &mi_ctx->pixel_weights[x + y * width];
900 ✗ PixelRefs *pixel_refs = &mi_ctx->pixel_refs[x + y * width];
901
902 ✗ ADD_PIXELS(obmc_weight, mv_x, mv_y);
903 }
904 }
905 }
906 ✗ }
907
908 8 static void set_frame_data(MIContext *mi_ctx, int alpha, AVFrame *avf_out)
909 {
910 int x, y, plane;
911
912
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8 times.
32 for (plane = 0; plane < mi_ctx->nb_planes; plane++) {
913 24 int width = avf_out->width;
914 24 int height = avf_out->height;
915
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;
916
917
2/2
✓ Branch 0 taken 5760 times.
✓ Branch 1 taken 24 times.
5784 for (y = 0; y < height; y++)
918
2/2
✓ Branch 0 taken 1843200 times.
✓ Branch 1 taken 5760 times.
1848960 for (x = 0; x < width; x++) {
919 int x_mv, y_mv;
920 1843200 int weight_sum = 0;
921 1843200 int i, val = 0;
922 1843200 PixelMVS *pixel_mvs = &mi_ctx->pixel_mvs[x + y * width];
923 1843200 PixelWeights *pixel_weights = &mi_ctx->pixel_weights[x + y * width];
924 1843200 PixelRefs *pixel_refs = &mi_ctx->pixel_refs[x + y * width];
925
926
2/2
✓ Branch 0 taken 13505936 times.
✓ Branch 1 taken 1843200 times.
15349136 for (i = 0; i < pixel_refs->nb; i++)
927 13505936 weight_sum += pixel_weights->weights[i];
928
929
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) {
930 4472 pixel_weights->weights[0] = ALPHA_MAX - alpha;
931 4472 pixel_refs->refs[0] = 1;
932 4472 pixel_mvs->mvs[0][0] = 0;
933 4472 pixel_mvs->mvs[0][1] = 0;
934 4472 pixel_weights->weights[1] = alpha;
935 4472 pixel_refs->refs[1] = 2;
936 4472 pixel_mvs->mvs[1][0] = 0;
937 4472 pixel_mvs->mvs[1][1] = 0;
938 4472 pixel_refs->nb = 2;
939
940 4472 weight_sum = ALPHA_MAX;
941 }
942
943
2/2
✓ Branch 0 taken 1228800 times.
✓ Branch 1 taken 614400 times.
1843200 if (chroma) {
944
2/2
✓ Branch 0 taken 9009920 times.
✓ Branch 1 taken 1228800 times.
10238720 for (i = 0; i < pixel_refs->nb; i++) {
945 9009920 Frame *frame = &mi_ctx->frames[pixel_refs->refs[i]];
946 9009920 x_mv = (x >> mi_ctx->log2_chroma_w) + pixel_mvs->mvs[i][0] / (1 << mi_ctx->log2_chroma_w);
947 9009920 y_mv = (y >> mi_ctx->log2_chroma_h) + pixel_mvs->mvs[i][1] / (1 << mi_ctx->log2_chroma_h);
948 9009920 val += pixel_weights->weights[i] * frame->avf->data[plane][x_mv + y_mv * frame->avf->linesize[plane]];
949 }
950 } else {
951
2/2
✓ Branch 0 taken 4504960 times.
✓ Branch 1 taken 614400 times.
5119360 for (i = 0; i < pixel_refs->nb; i++) {
952 4504960 Frame *frame = &mi_ctx->frames[pixel_refs->refs[i]];
953 4504960 x_mv = x + pixel_mvs->mvs[i][0];
954 4504960 y_mv = y + pixel_mvs->mvs[i][1];
955 4504960 val += pixel_weights->weights[i] * frame->avf->data[plane][x_mv + y_mv * frame->avf->linesize[plane]];
956 }
957 }
958
959
1/2
✓ Branch 0 taken 1843200 times.
✗ Branch 1 not taken.
1843200 val = ROUNDED_DIV(val, weight_sum);
960
961
2/2
✓ Branch 0 taken 1228800 times.
✓ Branch 1 taken 614400 times.
1843200 if (chroma)
962 1228800 avf_out->data[plane][(x >> mi_ctx->log2_chroma_w) + (y >> mi_ctx->log2_chroma_h) * avf_out->linesize[plane]] = val;
963 else
964 614400 avf_out->data[plane][x + y * avf_out->linesize[plane]] = val;
965 }
966 }
967 8 }
968
969 ✗ static void var_size_bmc(MIContext *mi_ctx, Block *block, int x_mb, int y_mb, int n, int alpha)
970 {
971 int sb_x, sb_y;
972 ✗ int width = mi_ctx->frames[0].avf->width;
973 ✗ int height = mi_ctx->frames[0].avf->height;
974
975 ✗ for (sb_y = 0; sb_y < 2; sb_y++)
976 ✗ for (sb_x = 0; sb_x < 2; sb_x++) {
977 ✗ Block *sb = &block->subs[sb_x + sb_y * 2];
978
979 ✗ if (sb->sb)
980 ✗ var_size_bmc(mi_ctx, sb, x_mb + (sb_x << (n - 1)), y_mb + (sb_y << (n - 1)), n - 1, alpha);
981 else {
982 int x, y;
983 ✗ int mv_x = sb->mvs[0][0] * 2;
984 ✗ int mv_y = sb->mvs[0][1] * 2;
985
986 ✗ int start_x = x_mb + (sb_x << (n - 1));
987 ✗ int start_y = y_mb + (sb_y << (n - 1));
988 ✗ int end_x = start_x + (1 << (n - 1));
989 ✗ int end_y = start_y + (1 << (n - 1));
990
991 ✗ for (y = start_y; y < end_y; y++) {
992 ✗ int y_min = -y;
993 ✗ int y_max = height - y - 1;
994 ✗ for (x = start_x; x < end_x; x++) {
995 ✗ int x_min = -x;
996 ✗ int x_max = width - x - 1;
997 ✗ PixelMVS *pixel_mvs = &mi_ctx->pixel_mvs[x + y * width];
998 ✗ PixelWeights *pixel_weights = &mi_ctx->pixel_weights[x + y * width];
999 ✗ PixelRefs *pixel_refs = &mi_ctx->pixel_refs[x + y * width];
1000
1001 ✗ ADD_PIXELS(PX_WEIGHT_MAX, mv_x, mv_y);
1002 }
1003 }
1004 }
1005 }
1006 ✗ }
1007
1008 2400 static void bilateral_obmc(MIContext *mi_ctx, Block *block, int mb_x, int mb_y, int alpha)
1009 {
1010 int x, y;
1011 2400 int width = mi_ctx->frames[0].avf->width;
1012 2400 int height = mi_ctx->frames[0].avf->height;
1013
1014 Block *nb;
1015 int nb_x, nb_y;
1016 uint64_t sbads[9];
1017
1018 2400 int mv_x = block->mvs[0][0] * 2;
1019 2400 int mv_y = block->mvs[0][1] * 2;
1020 int start_x, start_y;
1021 int startc_x, startc_y, endc_x, endc_y;
1022
1023
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2400 times.
2400 if (mi_ctx->mc_mode == MC_MODE_AOBMC)
1024 ✗ for (nb_y = FFMAX(0, mb_y - 1); nb_y < FFMIN(mb_y + 2, mi_ctx->b_height); nb_y++)
1025 ✗ for (nb_x = FFMAX(0, mb_x - 1); nb_x < FFMIN(mb_x + 2, mi_ctx->b_width); nb_x++) {
1026 ✗ int x_nb = nb_x << mi_ctx->log2_mb_size;
1027 ✗ int y_nb = nb_y << mi_ctx->log2_mb_size;
1028
1029 ✗ if (nb_x - mb_x || nb_y - mb_y)
1030 ✗ 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]);
1031 }
1032
1033 2400 start_x = (mb_x << mi_ctx->log2_mb_size) - mi_ctx->mb_size / 2;
1034 2400 start_y = (mb_y << mi_ctx->log2_mb_size) - mi_ctx->mb_size / 2;
1035
1036 2400 startc_x = av_clip(start_x, 0, width - 1);
1037 2400 startc_y = av_clip(start_y, 0, height - 1);
1038 2400 endc_x = av_clip(start_x + (2 << mi_ctx->log2_mb_size), 0, width - 1);
1039 2400 endc_y = av_clip(start_y + (2 << mi_ctx->log2_mb_size), 0, height - 1);
1040
1041
2/2
✓ Branch 0 taken 74080 times.
✓ Branch 1 taken 2400 times.
76480 for (y = startc_y; y < endc_y; y++) {
1042 74080 int y_min = -y;
1043 74080 int y_max = height - y - 1;
1044
2/2
✓ Branch 0 taken 2307592 times.
✓ Branch 1 taken 74080 times.
2381672 for (x = startc_x; x < endc_x; x++) {
1045 2307592 int x_min = -x;
1046 2307592 int x_max = width - x - 1;
1047 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))];
1048 2307592 PixelMVS *pixel_mvs = &mi_ctx->pixel_mvs[x + y * width];
1049 2307592 PixelWeights *pixel_weights = &mi_ctx->pixel_weights[x + y * width];
1050 2307592 PixelRefs *pixel_refs = &mi_ctx->pixel_refs[x + y * width];
1051
1052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2307592 times.
2307592 if (mi_ctx->mc_mode == MC_MODE_AOBMC) {
1053 ✗ nb_x = (((x - start_x) >> (mi_ctx->log2_mb_size - 1)) * 2 - 3) / 2;
1054 ✗ nb_y = (((y - start_y) >> (mi_ctx->log2_mb_size - 1)) * 2 - 3) / 2;
1055
1056 ✗ if (nb_x || nb_y) {
1057 ✗ uint64_t sbad = sbads[nb_x + 1 + (nb_y + 1) * 3];
1058 ✗ nb = &mi_ctx->int_blocks[mb_x + nb_x + (mb_y + nb_y) * mi_ctx->b_width];
1059
1060 ✗ if (sbad && sbad != UINT64_MAX && nb->sbad != UINT64_MAX) {
1061 ✗ int phi = av_clip(ALPHA_MAX * nb->sbad / sbad, 0, ALPHA_MAX);
1062 ✗ obmc_weight = obmc_weight * phi / ALPHA_MAX;
1063 }
1064 }
1065 }
1066
1067
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);
1068 }
1069 }
1070 2400 }
1071
1072 13 static void interpolate(AVFilterLink *inlink, AVFrame *avf_out)
1073 {
1074 13 AVFilterContext *ctx = inlink->dst;
1075 13 AVFilterLink *outlink = ctx->outputs[0];
1076 13 MIContext *mi_ctx = ctx->priv;
1077 int x, y;
1078 int plane, alpha;
1079 int64_t pts;
1080
1081 13 pts = av_rescale(avf_out->pts, (int64_t) ALPHA_MAX * outlink->time_base.num * inlink->time_base.den,
1082 13 (int64_t) outlink->time_base.den * inlink->time_base.num);
1083
1084
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) {
1085 13 alpha = (pts - mi_ctx->frames[1].avf->pts * ALPHA_MAX) / (mi_ctx->frames[2].avf->pts - mi_ctx->frames[1].avf->pts);
1086 13 alpha = av_clip(alpha, 0, ALPHA_MAX);
1087 } else {
1088 ✗ av_log(ctx, AV_LOG_DEBUG, "duplicate input PTS detected\n");
1089 ✗ alpha = 0;
1090 }
1091
1092
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) {
1093
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);
1094 5 return;
1095 }
1096
1097
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (mi_ctx->scene_changed) {
1098 ✗ av_log(ctx, AV_LOG_DEBUG, "scene changed, input pts %"PRId64"\n", mi_ctx->frames[1].avf->pts);
1099 /* duplicate frame */
1100 ✗ av_frame_copy(avf_out, alpha > ALPHA_MAX / 2 ? mi_ctx->frames[2].avf : mi_ctx->frames[1].avf);
1101 ✗ return;
1102 }
1103
1104
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) {
1105 ✗ case MI_MODE_DUP:
1106 ✗ av_frame_copy(avf_out, alpha > ALPHA_MAX / 2 ? mi_ctx->frames[2].avf : mi_ctx->frames[1].avf);
1107
1108 ✗ break;
1109 ✗ case MI_MODE_BLEND:
1110 ✗ for (plane = 0; plane < mi_ctx->nb_planes; plane++) {
1111 ✗ int width = avf_out->width;
1112 ✗ int height = avf_out->height;
1113
1114 ✗ if (plane == 1 || plane == 2) {
1115 ✗ width = AV_CEIL_RSHIFT(width, mi_ctx->log2_chroma_w);
1116 ✗ height = AV_CEIL_RSHIFT(height, mi_ctx->log2_chroma_h);
1117 }
1118
1119 ✗ for (y = 0; y < height; y++) {
1120 ✗ for (x = 0; x < width; x++) {
1121 ✗ avf_out->data[plane][x + y * avf_out->linesize[plane]] =
1122 ✗ (alpha * mi_ctx->frames[2].avf->data[plane][x + y * mi_ctx->frames[2].avf->linesize[plane]] +
1123 ✗ (ALPHA_MAX - alpha) * mi_ctx->frames[1].avf->data[plane][x + y * mi_ctx->frames[1].avf->linesize[plane]] + 512) >> 10;
1124 }
1125 }
1126 }
1127
1128 ✗ break;
1129 8 case MI_MODE_MCI:
1130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (mi_ctx->me_mode == ME_MODE_BIDIR) {
1131 ✗ bidirectional_obmc(mi_ctx, alpha);
1132 ✗ set_frame_data(mi_ctx, alpha, avf_out);
1133
1134
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 } else if (mi_ctx->me_mode == ME_MODE_BILAT) {
1135 int mb_x, mb_y;
1136 Block *block;
1137
1138
2/2
✓ Branch 0 taken 1920 times.
✓ Branch 1 taken 8 times.
1928 for (y = 0; y < mi_ctx->frames[0].avf->height; y++)
1139
2/2
✓ Branch 0 taken 614400 times.
✓ Branch 1 taken 1920 times.
616320 for (x = 0; x < mi_ctx->frames[0].avf->width; x++)
1140 614400 mi_ctx->pixel_refs[x + y * mi_ctx->frames[0].avf->width].nb = 0;
1141
1142
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++)
1143
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++) {
1144 2400 block = &mi_ctx->int_blocks[mb_x + mb_y * mi_ctx->b_width];
1145
1146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2400 times.
2400 if (block->sb)
1147 ✗ 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);
1148
1149 2400 bilateral_obmc(mi_ctx, block, mb_x, mb_y, alpha);
1150
1151 }
1152
1153 8 set_frame_data(mi_ctx, alpha, avf_out);
1154 }
1155
1156 8 break;
1157 }
1158 }
1159
1160 8 static int filter_frame(AVFilterLink *inlink, AVFrame *avf_in)
1161 {
1162 8 AVFilterContext *ctx = inlink->dst;
1163 8 AVFilterLink *outlink = ctx->outputs[0];
1164 8 MIContext *mi_ctx = ctx->priv;
1165 int ret;
1166
1167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (avf_in->pts == AV_NOPTS_VALUE) {
1168 ✗ ret = ff_filter_frame(ctx->outputs[0], avf_in);
1169 ✗ return ret;
1170 }
1171
1172
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) {
1173 2 av_log(ctx, AV_LOG_VERBOSE, "Initializing out pts from input pts %"PRId64"\n", avf_in->pts);
1174 2 mi_ctx->out_pts = av_rescale_q(avf_in->pts, inlink->time_base, outlink->time_base);
1175 }
1176
1177
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 if (!mi_ctx->frames[NB_FRAMES - 1].avf)
1178
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (ret = inject_frame(inlink, av_frame_clone(avf_in)))
1179 ✗ return ret;
1180
1181
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (ret = inject_frame(inlink, avf_in))
1182 ✗ return ret;
1183
1184
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (!mi_ctx->frames[0].avf)
1185 4 return 0;
1186
1187 4 mi_ctx->scene_changed = detect_scene_change(ctx);
1188
1189 13 for (;;) {
1190 AVFrame *avf_out;
1191
1192
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)
1193 4 break;
1194
1195
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)))
1196 ✗ return AVERROR(ENOMEM);
1197
1198 13 av_frame_copy_props(avf_out, mi_ctx->frames[NB_FRAMES - 1].avf);
1199 13 avf_out->pts = mi_ctx->out_pts++;
1200 13 avf_out->duration = 1;
1201
1202 13 interpolate(inlink, avf_out);
1203
1204
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 if ((ret = ff_filter_frame(ctx->outputs[0], avf_out)) < 0)
1205 ✗ return ret;
1206 }
1207
1208 4 return 0;
1209 }
1210
1211 600 static av_cold void free_blocks(Block *block, int sb)
1212 {
1213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 600 times.
600 if (block->subs)
1214 ✗ free_blocks(block->subs, 1);
1215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 600 times.
600 if (sb)
1216 ✗ av_freep(&block);
1217 600 }
1218
1219 4 static av_cold void uninit(AVFilterContext *ctx)
1220 {
1221 4 MIContext *mi_ctx = ctx->priv;
1222 int i, m;
1223
1224 4 av_freep(&mi_ctx->pixel_mvs);
1225 4 av_freep(&mi_ctx->pixel_weights);
1226 4 av_freep(&mi_ctx->pixel_refs);
1227
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (mi_ctx->int_blocks)
1228
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 2 times.
602 for (m = 0; m < mi_ctx->b_count; m++)
1229 600 free_blocks(&mi_ctx->int_blocks[m], 0);
1230 4 av_freep(&mi_ctx->int_blocks);
1231
1232
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (i = 0; i < NB_FRAMES; i++) {
1233 16 Frame *frame = &mi_ctx->frames[i];
1234 16 av_freep(&frame->blocks);
1235 16 av_frame_free(&frame->avf);
1236 }
1237
1238
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
16 for (i = 0; i < 3; i++)
1239 12 av_freep(&mi_ctx->mv_table[i]);
1240 4 }
1241
1242 static const AVFilterPad minterpolate_inputs[] = {
1243 {
1244 .name = "default",
1245 .type = AVMEDIA_TYPE_VIDEO,
1246 .filter_frame = filter_frame,
1247 .config_props = config_input,
1248 },
1249 };
1250
1251 static const AVFilterPad minterpolate_outputs[] = {
1252 {
1253 .name = "default",
1254 .type = AVMEDIA_TYPE_VIDEO,
1255 .config_props = config_output,
1256 },
1257 };
1258
1259 const FFFilter ff_vf_minterpolate = {
1260 .p.name = "minterpolate",
1261 .p.description = NULL_IF_CONFIG_SMALL("Frame rate conversion using Motion Interpolation."),
1262 .p.priv_class = &minterpolate_class,
1263 .priv_size = sizeof(MIContext),
1264 .uninit = uninit,
1265 FILTER_INPUTS(minterpolate_inputs),
1266 FILTER_OUTPUTS(minterpolate_outputs),
1267 FILTER_PIXFMTS_ARRAY(pix_fmts),
1268 };
1269