FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavfilter/vf_minterpolate.c
Date: 2026-04-30 13:16:32
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