FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavfilter/vf_minterpolate.c
Date: 2024-04-23 06:12:56
Exec Total Coverage
Lines: 296 611 48.4%
Functions: 13 19 68.4%
Branches: 143 402 35.6%

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