Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * Copyright (c) 2007 Bobby Bingham | ||
3 | * | ||
4 | * This file is part of FFmpeg. | ||
5 | * | ||
6 | * FFmpeg is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU Lesser General Public | ||
8 | * License as published by the Free Software Foundation; either | ||
9 | * version 2.1 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * FFmpeg is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * Lesser General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU Lesser General Public | ||
17 | * License along with FFmpeg; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file | ||
23 | * scale video filter | ||
24 | */ | ||
25 | |||
26 | #include <float.h> | ||
27 | #include <stdio.h> | ||
28 | #include <string.h> | ||
29 | |||
30 | #include "avfilter.h" | ||
31 | #include "filters.h" | ||
32 | #include "formats.h" | ||
33 | #include "framesync.h" | ||
34 | #include "libavutil/pixfmt.h" | ||
35 | #include "scale_eval.h" | ||
36 | #include "video.h" | ||
37 | #include "libavutil/eval.h" | ||
38 | #include "libavutil/imgutils_internal.h" | ||
39 | #include "libavutil/internal.h" | ||
40 | #include "libavutil/mem.h" | ||
41 | #include "libavutil/opt.h" | ||
42 | #include "libavutil/parseutils.h" | ||
43 | #include "libavutil/pixdesc.h" | ||
44 | #include "libswscale/swscale.h" | ||
45 | |||
46 | static const char *const var_names[] = { | ||
47 | "in_w", "iw", | ||
48 | "in_h", "ih", | ||
49 | "out_w", "ow", | ||
50 | "out_h", "oh", | ||
51 | "a", | ||
52 | "sar", | ||
53 | "dar", | ||
54 | "hsub", | ||
55 | "vsub", | ||
56 | "ohsub", | ||
57 | "ovsub", | ||
58 | "n", | ||
59 | "t", | ||
60 | "ref_w", "rw", | ||
61 | "ref_h", "rh", | ||
62 | "ref_a", | ||
63 | "ref_sar", | ||
64 | "ref_dar", "rdar", | ||
65 | "ref_hsub", | ||
66 | "ref_vsub", | ||
67 | "ref_n", | ||
68 | "ref_t", | ||
69 | "ref_pos", | ||
70 | /* Legacy variables for scale2ref */ | ||
71 | "main_w", | ||
72 | "main_h", | ||
73 | "main_a", | ||
74 | "main_sar", | ||
75 | "main_dar", "mdar", | ||
76 | "main_hsub", | ||
77 | "main_vsub", | ||
78 | "main_n", | ||
79 | "main_t", | ||
80 | "main_pos", | ||
81 | NULL | ||
82 | }; | ||
83 | |||
84 | enum var_name { | ||
85 | VAR_IN_W, VAR_IW, | ||
86 | VAR_IN_H, VAR_IH, | ||
87 | VAR_OUT_W, VAR_OW, | ||
88 | VAR_OUT_H, VAR_OH, | ||
89 | VAR_A, | ||
90 | VAR_SAR, | ||
91 | VAR_DAR, | ||
92 | VAR_HSUB, | ||
93 | VAR_VSUB, | ||
94 | VAR_OHSUB, | ||
95 | VAR_OVSUB, | ||
96 | VAR_N, | ||
97 | VAR_T, | ||
98 | VAR_REF_W, VAR_RW, | ||
99 | VAR_REF_H, VAR_RH, | ||
100 | VAR_REF_A, | ||
101 | VAR_REF_SAR, | ||
102 | VAR_REF_DAR, VAR_RDAR, | ||
103 | VAR_REF_HSUB, | ||
104 | VAR_REF_VSUB, | ||
105 | VAR_REF_N, | ||
106 | VAR_REF_T, | ||
107 | VAR_REF_POS, | ||
108 | VAR_S2R_MAIN_W, | ||
109 | VAR_S2R_MAIN_H, | ||
110 | VAR_S2R_MAIN_A, | ||
111 | VAR_S2R_MAIN_SAR, | ||
112 | VAR_S2R_MAIN_DAR, VAR_S2R_MDAR, | ||
113 | VAR_S2R_MAIN_HSUB, | ||
114 | VAR_S2R_MAIN_VSUB, | ||
115 | VAR_S2R_MAIN_N, | ||
116 | VAR_S2R_MAIN_T, | ||
117 | VAR_S2R_MAIN_POS, | ||
118 | VARS_NB | ||
119 | }; | ||
120 | |||
121 | enum EvalMode { | ||
122 | EVAL_MODE_INIT, | ||
123 | EVAL_MODE_FRAME, | ||
124 | EVAL_MODE_NB | ||
125 | }; | ||
126 | |||
127 | typedef struct ScaleContext { | ||
128 | const AVClass *class; | ||
129 | SwsContext *sws; | ||
130 | FFFrameSync fs; | ||
131 | |||
132 | /** | ||
133 | * New dimensions. Special values are: | ||
134 | * 0 = original width/height | ||
135 | * -1 = keep original aspect | ||
136 | * -N = try to keep aspect but make sure it is divisible by N | ||
137 | */ | ||
138 | int w, h; | ||
139 | char *size_str; | ||
140 | double param[2]; // sws params | ||
141 | |||
142 | int hsub, vsub; ///< chroma subsampling | ||
143 | int slice_y; ///< top of current output slice | ||
144 | int interlaced; | ||
145 | int uses_ref; | ||
146 | |||
147 | char *w_expr; ///< width expression string | ||
148 | char *h_expr; ///< height expression string | ||
149 | AVExpr *w_pexpr; | ||
150 | AVExpr *h_pexpr; | ||
151 | double var_values[VARS_NB]; | ||
152 | |||
153 | char *flags_str; | ||
154 | |||
155 | int in_color_matrix; | ||
156 | int out_color_matrix; | ||
157 | int in_primaries; | ||
158 | int out_primaries; | ||
159 | int in_transfer; | ||
160 | int out_transfer; | ||
161 | int in_range; | ||
162 | int out_range; | ||
163 | |||
164 | int in_chroma_loc; | ||
165 | int out_chroma_loc; | ||
166 | int out_h_chr_pos; | ||
167 | int out_v_chr_pos; | ||
168 | int in_h_chr_pos; | ||
169 | int in_v_chr_pos; | ||
170 | |||
171 | int force_original_aspect_ratio; | ||
172 | int force_divisible_by; | ||
173 | int reset_sar; | ||
174 | |||
175 | int eval_mode; ///< expression evaluation mode | ||
176 | |||
177 | } ScaleContext; | ||
178 | |||
179 | const FFFilter ff_vf_scale2ref; | ||
180 | #define IS_SCALE2REF(ctx) ((ctx)->filter == &ff_vf_scale2ref.p) | ||
181 | |||
182 | static int config_props(AVFilterLink *outlink); | ||
183 | |||
184 | 21614 | static int check_exprs(AVFilterContext *ctx) | |
185 | { | ||
186 | 21614 | ScaleContext *scale = ctx->priv; | |
187 | 21614 | unsigned vars_w[VARS_NB] = { 0 }, vars_h[VARS_NB] = { 0 }; | |
188 | |||
189 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 21614 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
21614 | if (!scale->w_pexpr && !scale->h_pexpr) |
190 | ✗ | return AVERROR(EINVAL); | |
191 | |||
192 |
1/2✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
|
21614 | if (scale->w_pexpr) |
193 | 21614 | av_expr_count_vars(scale->w_pexpr, vars_w, VARS_NB); | |
194 |
2/2✓ Branch 0 taken 10825 times.
✓ Branch 1 taken 10789 times.
|
21614 | if (scale->h_pexpr) |
195 | 10825 | av_expr_count_vars(scale->h_pexpr, vars_h, VARS_NB); | |
196 | |||
197 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21614 times.
|
21614 | if (vars_w[VAR_OUT_W] || vars_w[VAR_OW]) { |
198 | ✗ | av_log(ctx, AV_LOG_ERROR, "Width expression cannot be self-referencing: '%s'.\n", scale->w_expr); | |
199 | ✗ | return AVERROR(EINVAL); | |
200 | } | ||
201 | |||
202 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21614 times.
|
21614 | if (vars_h[VAR_OUT_H] || vars_h[VAR_OH]) { |
203 | ✗ | av_log(ctx, AV_LOG_ERROR, "Height expression cannot be self-referencing: '%s'.\n", scale->h_expr); | |
204 | ✗ | return AVERROR(EINVAL); | |
205 | } | ||
206 | |||
207 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21614 times.
|
21614 | if ((vars_w[VAR_OUT_H] || vars_w[VAR_OH]) && |
208 | ✗ | (vars_h[VAR_OUT_W] || vars_h[VAR_OW])) { | |
209 | ✗ | av_log(ctx, AV_LOG_WARNING, "Circular references detected for width '%s' and height '%s' - possibly invalid.\n", scale->w_expr, scale->h_expr); | |
210 | } | ||
211 | |||
212 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21614 times.
✗ Branch 3 not taken.
|
21614 | if (vars_w[VAR_REF_W] || vars_h[VAR_REF_W] || |
213 |
3/4✓ Branch 0 taken 21610 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 21610 times.
✗ Branch 3 not taken.
|
21614 | vars_w[VAR_RW] || vars_h[VAR_RW] || |
214 |
2/4✓ Branch 0 taken 21610 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21610 times.
✗ Branch 3 not taken.
|
21610 | vars_w[VAR_REF_H] || vars_h[VAR_REF_H] || |
215 |
2/4✓ Branch 0 taken 21610 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21610 times.
✗ Branch 3 not taken.
|
21610 | vars_w[VAR_RH] || vars_h[VAR_RH] || |
216 |
2/4✓ Branch 0 taken 21610 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21610 times.
✗ Branch 3 not taken.
|
21610 | vars_w[VAR_REF_A] || vars_h[VAR_REF_A] || |
217 |
2/4✓ Branch 0 taken 21610 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21610 times.
✗ Branch 3 not taken.
|
21610 | vars_w[VAR_REF_SAR] || vars_h[VAR_REF_SAR] || |
218 |
2/4✓ Branch 0 taken 21610 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21610 times.
✗ Branch 3 not taken.
|
21610 | vars_w[VAR_REF_DAR] || vars_h[VAR_REF_DAR] || |
219 |
2/4✓ Branch 0 taken 21610 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21610 times.
✗ Branch 3 not taken.
|
21610 | vars_w[VAR_RDAR] || vars_h[VAR_RDAR] || |
220 |
2/4✓ Branch 0 taken 21610 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21610 times.
✗ Branch 3 not taken.
|
21610 | vars_w[VAR_REF_HSUB] || vars_h[VAR_REF_HSUB] || |
221 |
2/4✓ Branch 0 taken 21610 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21610 times.
✗ Branch 3 not taken.
|
21610 | vars_w[VAR_REF_VSUB] || vars_h[VAR_REF_VSUB] || |
222 |
2/4✓ Branch 0 taken 21610 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21610 times.
✗ Branch 3 not taken.
|
21610 | vars_w[VAR_REF_N] || vars_h[VAR_REF_N] || |
223 |
2/4✓ Branch 0 taken 21610 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21610 times.
✗ Branch 3 not taken.
|
21610 | vars_w[VAR_REF_T] || vars_h[VAR_REF_T] || |
224 |
2/4✓ Branch 0 taken 21610 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21610 times.
|
21610 | vars_w[VAR_REF_POS] || vars_h[VAR_REF_POS]) { |
225 | 4 | scale->uses_ref = 1; | |
226 | } | ||
227 | |||
228 |
1/2✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
|
21614 | if (!IS_SCALE2REF(ctx) && |
229 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21614 times.
✗ Branch 3 not taken.
|
21614 | (vars_w[VAR_S2R_MAIN_W] || vars_h[VAR_S2R_MAIN_W] || |
230 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21614 times.
✗ Branch 3 not taken.
|
21614 | vars_w[VAR_S2R_MAIN_H] || vars_h[VAR_S2R_MAIN_H] || |
231 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21614 times.
✗ Branch 3 not taken.
|
21614 | vars_w[VAR_S2R_MAIN_A] || vars_h[VAR_S2R_MAIN_A] || |
232 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21614 times.
✗ Branch 3 not taken.
|
21614 | vars_w[VAR_S2R_MAIN_SAR] || vars_h[VAR_S2R_MAIN_SAR] || |
233 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21614 times.
✗ Branch 3 not taken.
|
21614 | vars_w[VAR_S2R_MAIN_DAR] || vars_h[VAR_S2R_MAIN_DAR] || |
234 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21614 times.
✗ Branch 3 not taken.
|
21614 | vars_w[VAR_S2R_MDAR] || vars_h[VAR_S2R_MDAR] || |
235 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21614 times.
✗ Branch 3 not taken.
|
21614 | vars_w[VAR_S2R_MAIN_HSUB] || vars_h[VAR_S2R_MAIN_HSUB] || |
236 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21614 times.
✗ Branch 3 not taken.
|
21614 | vars_w[VAR_S2R_MAIN_VSUB] || vars_h[VAR_S2R_MAIN_VSUB] || |
237 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21614 times.
✗ Branch 3 not taken.
|
21614 | vars_w[VAR_S2R_MAIN_N] || vars_h[VAR_S2R_MAIN_N] || |
238 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21614 times.
✗ Branch 3 not taken.
|
21614 | vars_w[VAR_S2R_MAIN_T] || vars_h[VAR_S2R_MAIN_T] || |
239 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21614 times.
|
21614 | vars_w[VAR_S2R_MAIN_POS] || vars_h[VAR_S2R_MAIN_POS]) ) { |
240 | ✗ | av_log(ctx, AV_LOG_ERROR, "Expressions with scale2ref variables are not valid in scale filter.\n"); | |
241 | ✗ | return AVERROR(EINVAL); | |
242 | } | ||
243 | |||
244 |
1/2✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
|
21614 | if (scale->eval_mode == EVAL_MODE_INIT && |
245 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21614 times.
✗ Branch 3 not taken.
|
21614 | (vars_w[VAR_N] || vars_h[VAR_N] || |
246 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21614 times.
✗ Branch 3 not taken.
|
21614 | vars_w[VAR_T] || vars_h[VAR_T] || |
247 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21614 times.
✗ Branch 3 not taken.
|
21614 | vars_w[VAR_S2R_MAIN_N] || vars_h[VAR_S2R_MAIN_N] || |
248 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21614 times.
✗ Branch 3 not taken.
|
21614 | vars_w[VAR_S2R_MAIN_T] || vars_h[VAR_S2R_MAIN_T] || |
249 |
2/4✓ Branch 0 taken 21614 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21614 times.
|
21614 | vars_w[VAR_S2R_MAIN_POS] || vars_h[VAR_S2R_MAIN_POS]) ) { |
250 | ✗ | av_log(ctx, AV_LOG_ERROR, "Expressions with frame variables 'n', 't', 'pos' are not valid in init eval_mode.\n"); | |
251 | ✗ | return AVERROR(EINVAL); | |
252 | } | ||
253 | |||
254 | 21614 | return 0; | |
255 | } | ||
256 | |||
257 | 21614 | static int scale_parse_expr(AVFilterContext *ctx, char *str_expr, AVExpr **pexpr_ptr, const char *var, const char *args) | |
258 | { | ||
259 | 21614 | ScaleContext *scale = ctx->priv; | |
260 | 21614 | int ret, is_inited = 0; | |
261 | 21614 | char *old_str_expr = NULL; | |
262 | 21614 | AVExpr *old_pexpr = NULL; | |
263 | |||
264 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21614 times.
|
21614 | if (str_expr) { |
265 | ✗ | old_str_expr = av_strdup(str_expr); | |
266 | ✗ | if (!old_str_expr) | |
267 | ✗ | return AVERROR(ENOMEM); | |
268 | ✗ | av_opt_set(scale, var, args, 0); | |
269 | } | ||
270 | |||
271 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 21578 times.
|
21614 | if (*pexpr_ptr) { |
272 | 36 | old_pexpr = *pexpr_ptr; | |
273 | 36 | *pexpr_ptr = NULL; | |
274 | 36 | is_inited = 1; | |
275 | } | ||
276 | |||
277 | 21614 | ret = av_expr_parse(pexpr_ptr, args, var_names, | |
278 | NULL, NULL, NULL, NULL, 0, ctx); | ||
279 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21614 times.
|
21614 | if (ret < 0) { |
280 | ✗ | av_log(ctx, AV_LOG_ERROR, "Cannot parse expression for %s: '%s'\n", var, args); | |
281 | ✗ | goto revert; | |
282 | } | ||
283 | |||
284 | 21614 | ret = check_exprs(ctx); | |
285 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21614 times.
|
21614 | if (ret < 0) |
286 | ✗ | goto revert; | |
287 | |||
288 |
3/4✓ Branch 0 taken 36 times.
✓ Branch 1 taken 21578 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 36 times.
|
21614 | if (is_inited && (ret = config_props(ctx->outputs[0])) < 0) |
289 | ✗ | goto revert; | |
290 | |||
291 | 21614 | av_expr_free(old_pexpr); | |
292 | 21614 | old_pexpr = NULL; | |
293 | 21614 | av_freep(&old_str_expr); | |
294 | |||
295 | 21614 | return 0; | |
296 | |||
297 | ✗ | revert: | |
298 | ✗ | av_expr_free(*pexpr_ptr); | |
299 | ✗ | *pexpr_ptr = NULL; | |
300 | ✗ | if (old_str_expr) { | |
301 | ✗ | av_opt_set(scale, var, old_str_expr, 0); | |
302 | ✗ | av_free(old_str_expr); | |
303 | } | ||
304 | ✗ | if (old_pexpr) | |
305 | ✗ | *pexpr_ptr = old_pexpr; | |
306 | |||
307 | ✗ | return ret; | |
308 | } | ||
309 | |||
310 | 10789 | static av_cold int preinit(AVFilterContext *ctx) | |
311 | { | ||
312 | 10789 | ScaleContext *scale = ctx->priv; | |
313 | |||
314 | 10789 | scale->sws = sws_alloc_context(); | |
315 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10789 times.
|
10789 | if (!scale->sws) |
316 | ✗ | return AVERROR(ENOMEM); | |
317 | |||
318 | // set threads=0, so we can later check whether the user modified it | ||
319 | 10789 | scale->sws->threads = 0; | |
320 | |||
321 | 10789 | ff_framesync_preinit(&scale->fs); | |
322 | |||
323 | 10789 | return 0; | |
324 | } | ||
325 | |||
326 | static int do_scale(FFFrameSync *fs); | ||
327 | |||
328 | 10789 | static av_cold int init(AVFilterContext *ctx) | |
329 | { | ||
330 | 10789 | ScaleContext *scale = ctx->priv; | |
331 | int ret; | ||
332 | |||
333 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10789 times.
|
10789 | if (IS_SCALE2REF(ctx)) |
334 | ✗ | av_log(ctx, AV_LOG_WARNING, "scale2ref is deprecated, use scale=rw:rh instead\n"); | |
335 | |||
336 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 10789 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
10789 | if (scale->size_str && (scale->w_expr || scale->h_expr)) { |
337 | ✗ | av_log(ctx, AV_LOG_ERROR, | |
338 | "Size and width/height expressions cannot be set at the same time.\n"); | ||
339 | ✗ | return AVERROR(EINVAL); | |
340 | } | ||
341 | |||
342 |
3/4✓ Branch 0 taken 1786 times.
✓ Branch 1 taken 9003 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1786 times.
|
10789 | if (scale->w_expr && !scale->h_expr) |
343 | ✗ | FFSWAP(char *, scale->w_expr, scale->size_str); | |
344 | |||
345 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10789 times.
|
10789 | if (scale->size_str) { |
346 | char buf[32]; | ||
347 | ✗ | if ((ret = av_parse_video_size(&scale->w, &scale->h, scale->size_str)) < 0) { | |
348 | ✗ | av_log(ctx, AV_LOG_ERROR, | |
349 | "Invalid size '%s'\n", scale->size_str); | ||
350 | ✗ | return ret; | |
351 | } | ||
352 | ✗ | snprintf(buf, sizeof(buf)-1, "%d", scale->w); | |
353 | ✗ | av_opt_set(scale, "w", buf, 0); | |
354 | ✗ | snprintf(buf, sizeof(buf)-1, "%d", scale->h); | |
355 | ✗ | av_opt_set(scale, "h", buf, 0); | |
356 | } | ||
357 |
2/2✓ Branch 0 taken 9003 times.
✓ Branch 1 taken 1786 times.
|
10789 | if (!scale->w_expr) |
358 | 9003 | av_opt_set(scale, "w", "iw", 0); | |
359 |
2/2✓ Branch 0 taken 9003 times.
✓ Branch 1 taken 1786 times.
|
10789 | if (!scale->h_expr) |
360 | 9003 | av_opt_set(scale, "h", "ih", 0); | |
361 | |||
362 | 10789 | ret = scale_parse_expr(ctx, NULL, &scale->w_pexpr, "width", scale->w_expr); | |
363 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10789 times.
|
10789 | if (ret < 0) |
364 | ✗ | return ret; | |
365 | |||
366 | 10789 | ret = scale_parse_expr(ctx, NULL, &scale->h_pexpr, "height", scale->h_expr); | |
367 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10789 times.
|
10789 | if (ret < 0) |
368 | ✗ | return ret; | |
369 | |||
370 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 10789 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
10789 | if (scale->in_primaries != -1 && !sws_test_primaries(scale->in_primaries, 0)) { |
371 | ✗ | av_log(ctx, AV_LOG_ERROR, "Unsupported input primaries '%s'\n", | |
372 | ✗ | av_color_primaries_name(scale->in_primaries)); | |
373 | ✗ | return AVERROR(EINVAL); | |
374 | } | ||
375 | |||
376 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 10789 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
10789 | if (scale->out_primaries != -1 && !sws_test_primaries(scale->out_primaries, 1)) { |
377 | ✗ | av_log(ctx, AV_LOG_ERROR, "Unsupported output primaries '%s'\n", | |
378 | ✗ | av_color_primaries_name(scale->out_primaries)); | |
379 | ✗ | return AVERROR(EINVAL); | |
380 | } | ||
381 | |||
382 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 10789 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
10789 | if (scale->in_transfer != -1 && !sws_test_transfer(scale->in_transfer, 0)) { |
383 | ✗ | av_log(ctx, AV_LOG_ERROR, "Unsupported input transfer '%s'\n", | |
384 | ✗ | av_color_transfer_name(scale->in_transfer)); | |
385 | ✗ | return AVERROR(EINVAL); | |
386 | } | ||
387 | |||
388 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 10789 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
10789 | if (scale->out_transfer != -1 && !sws_test_transfer(scale->out_transfer, 1)) { |
389 | ✗ | av_log(ctx, AV_LOG_ERROR, "Unsupported output transfer '%s'\n", | |
390 | ✗ | av_color_transfer_name(scale->out_transfer)); | |
391 | ✗ | return AVERROR(EINVAL); | |
392 | } | ||
393 | |||
394 |
3/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 10785 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
|
10789 | if (scale->in_color_matrix != -1 && !sws_test_colorspace(scale->in_color_matrix, 0)) { |
395 | ✗ | av_log(ctx, AV_LOG_ERROR, "Unsupported input color matrix '%s'\n", | |
396 | ✗ | av_color_space_name(scale->in_color_matrix)); | |
397 | ✗ | return AVERROR(EINVAL); | |
398 | } | ||
399 | |||
400 |
2/4✓ Branch 0 taken 10789 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 10789 times.
|
10789 | if (scale->out_color_matrix != -1 && !sws_test_colorspace(scale->out_color_matrix, 1)) { |
401 | ✗ | av_log(ctx, AV_LOG_ERROR, "Unsupported output color matrix '%s'\n", | |
402 | ✗ | av_color_space_name(scale->out_color_matrix)); | |
403 | ✗ | return AVERROR(EINVAL); | |
404 | } | ||
405 | |||
406 | 10789 | av_log(ctx, AV_LOG_VERBOSE, "w:%s h:%s flags:'%s' interl:%d\n", | |
407 | 10789 | scale->w_expr, scale->h_expr, (char *)av_x_if_null(scale->flags_str, ""), scale->interlaced); | |
408 | |||
409 |
3/4✓ Branch 0 taken 10789 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2142 times.
✓ Branch 3 taken 8647 times.
|
10789 | if (scale->flags_str && *scale->flags_str) { |
410 | 2142 | ret = av_opt_set(scale->sws, "sws_flags", scale->flags_str, 0); | |
411 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2142 times.
|
2142 | if (ret < 0) |
412 | ✗ | return ret; | |
413 | } | ||
414 | |||
415 |
2/2✓ Branch 0 taken 21578 times.
✓ Branch 1 taken 10789 times.
|
32367 | for (int i = 0; i < FF_ARRAY_ELEMS(scale->param); i++) |
416 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21578 times.
|
21578 | if (scale->param[i] != DBL_MAX) |
417 | ✗ | scale->sws->scaler_params[i] = scale->param[i]; | |
418 | |||
419 | 10789 | scale->sws->src_h_chr_pos = scale->in_h_chr_pos; | |
420 | 10789 | scale->sws->src_v_chr_pos = scale->in_v_chr_pos; | |
421 | 10789 | scale->sws->dst_h_chr_pos = scale->out_h_chr_pos; | |
422 | 10789 | scale->sws->dst_v_chr_pos = scale->out_v_chr_pos; | |
423 | |||
424 | // use generic thread-count if the user did not set it explicitly | ||
425 |
1/2✓ Branch 0 taken 10789 times.
✗ Branch 1 not taken.
|
10789 | if (!scale->sws->threads) |
426 | 10789 | scale->sws->threads = ff_filter_get_nb_threads(ctx); | |
427 | |||
428 |
3/4✓ Branch 0 taken 10789 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 10787 times.
|
10789 | if (!IS_SCALE2REF(ctx) && scale->uses_ref) { |
429 | 2 | AVFilterPad pad = { | |
430 | .name = "ref", | ||
431 | .type = AVMEDIA_TYPE_VIDEO, | ||
432 | }; | ||
433 | 2 | ret = ff_append_inpad(ctx, &pad); | |
434 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (ret < 0) |
435 | ✗ | return ret; | |
436 | } | ||
437 | |||
438 | 10789 | return 0; | |
439 | } | ||
440 | |||
441 | 10789 | static av_cold void uninit(AVFilterContext *ctx) | |
442 | { | ||
443 | 10789 | ScaleContext *scale = ctx->priv; | |
444 | 10789 | av_expr_free(scale->w_pexpr); | |
445 | 10789 | av_expr_free(scale->h_pexpr); | |
446 | 10789 | scale->w_pexpr = scale->h_pexpr = NULL; | |
447 | 10789 | ff_framesync_uninit(&scale->fs); | |
448 | 10789 | sws_free_context(&scale->sws); | |
449 | 10789 | } | |
450 | |||
451 | 6407 | static int query_formats(const AVFilterContext *ctx, | |
452 | AVFilterFormatsConfig **cfg_in, | ||
453 | AVFilterFormatsConfig **cfg_out) | ||
454 | { | ||
455 | 6407 | const ScaleContext *scale = ctx->priv; | |
456 | AVFilterFormats *formats; | ||
457 | const AVPixFmtDescriptor *desc; | ||
458 | enum AVPixelFormat pix_fmt; | ||
459 | int ret; | ||
460 | |||
461 | 6407 | desc = NULL; | |
462 | 6407 | formats = NULL; | |
463 |
2/2✓ Branch 1 taken 1653006 times.
✓ Branch 2 taken 6407 times.
|
1659413 | while ((desc = av_pix_fmt_desc_next(desc))) { |
464 | 1653006 | pix_fmt = av_pix_fmt_desc_get_id(desc); | |
465 |
2/2✓ Branch 1 taken 1435168 times.
✓ Branch 2 taken 217838 times.
|
1653006 | if (sws_test_format(pix_fmt, 0)) { |
466 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1435168 times.
|
1435168 | if ((ret = ff_add_format(&formats, pix_fmt)) < 0) |
467 | ✗ | return ret; | |
468 | } | ||
469 | } | ||
470 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6407 times.
|
6407 | if ((ret = ff_formats_ref(formats, &cfg_in[0]->formats)) < 0) |
471 | ✗ | return ret; | |
472 | |||
473 | 6407 | desc = NULL; | |
474 | 6407 | formats = NULL; | |
475 |
2/2✓ Branch 1 taken 1653006 times.
✓ Branch 2 taken 6407 times.
|
1659413 | while ((desc = av_pix_fmt_desc_next(desc))) { |
476 | 1653006 | pix_fmt = av_pix_fmt_desc_get_id(desc); | |
477 |
4/4✓ Branch 1 taken 397234 times.
✓ Branch 2 taken 1255772 times.
✓ Branch 3 taken 6407 times.
✓ Branch 4 taken 390827 times.
|
1653006 | if (sws_test_format(pix_fmt, 1) || pix_fmt == AV_PIX_FMT_PAL8) { |
478 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1262179 times.
|
1262179 | if ((ret = ff_add_format(&formats, pix_fmt)) < 0) |
479 | ✗ | return ret; | |
480 | } | ||
481 | } | ||
482 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6407 times.
|
6407 | if ((ret = ff_formats_ref(formats, &cfg_out[0]->formats)) < 0) |
483 | ✗ | return ret; | |
484 | |||
485 | /* accept all supported inputs, even if user overrides their properties */ | ||
486 | 6407 | formats = ff_all_color_spaces(); | |
487 |
2/2✓ Branch 0 taken 108919 times.
✓ Branch 1 taken 6407 times.
|
115326 | for (int i = 0; i < formats->nb_formats; i++) { |
488 |
2/2✓ Branch 1 taken 57663 times.
✓ Branch 2 taken 51256 times.
|
108919 | if (!sws_test_colorspace(formats->formats[i], 0)) { |
489 |
2/2✓ Branch 0 taken 237059 times.
✓ Branch 1 taken 57663 times.
|
294722 | for (int j = i--; j + 1 < formats->nb_formats; j++) |
490 | 237059 | formats->formats[j] = formats->formats[j + 1]; | |
491 | 57663 | formats->nb_formats--; | |
492 | } | ||
493 | } | ||
494 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6407 times.
|
6407 | if ((ret = ff_formats_ref(formats, &cfg_in[0]->color_spaces)) < 0) |
495 | ✗ | return ret; | |
496 | |||
497 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6407 times.
|
6407 | if ((ret = ff_formats_ref(ff_all_color_ranges(), |
498 | 6407 | &cfg_in[0]->color_ranges)) < 0) | |
499 | ✗ | return ret; | |
500 | |||
501 | /* propagate output properties if overridden */ | ||
502 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6405 times.
|
6407 | if (scale->out_color_matrix != AVCOL_SPC_UNSPECIFIED) { |
503 | 2 | formats = ff_make_formats_list_singleton(scale->out_color_matrix); | |
504 | } else { | ||
505 | 6405 | formats = ff_all_color_spaces(); | |
506 |
2/2✓ Branch 0 taken 108885 times.
✓ Branch 1 taken 6405 times.
|
115290 | for (int i = 0; i < formats->nb_formats; i++) { |
507 |
2/2✓ Branch 1 taken 57645 times.
✓ Branch 2 taken 51240 times.
|
108885 | if (!sws_test_colorspace(formats->formats[i], 1)) { |
508 |
2/2✓ Branch 0 taken 236985 times.
✓ Branch 1 taken 57645 times.
|
294630 | for (int j = i--; j + 1 < formats->nb_formats; j++) |
509 | 236985 | formats->formats[j] = formats->formats[j + 1]; | |
510 | 57645 | formats->nb_formats--; | |
511 | } | ||
512 | } | ||
513 | } | ||
514 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6407 times.
|
6407 | if ((ret = ff_formats_ref(formats, &cfg_out[0]->color_spaces)) < 0) |
515 | ✗ | return ret; | |
516 | |||
517 | 12814 | formats = scale->out_range != AVCOL_RANGE_UNSPECIFIED | |
518 | 2 | ? ff_make_formats_list_singleton(scale->out_range) | |
519 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6405 times.
|
6407 | : ff_all_color_ranges(); |
520 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6407 times.
|
6407 | if ((ret = ff_formats_ref(formats, &cfg_out[0]->color_ranges)) < 0) |
521 | ✗ | return ret; | |
522 | |||
523 | 6407 | return 0; | |
524 | } | ||
525 | |||
526 | 6416 | static int scale_eval_dimensions(AVFilterContext *ctx) | |
527 | { | ||
528 | 6416 | ScaleContext *scale = ctx->priv; | |
529 | 6416 | const char scale2ref = IS_SCALE2REF(ctx); | |
530 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6416 times.
|
6416 | const AVFilterLink *inlink = scale2ref ? ctx->inputs[1] : ctx->inputs[0]; |
531 | 6416 | const AVFilterLink *outlink = ctx->outputs[0]; | |
532 | 6416 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); | |
533 | 6416 | const AVPixFmtDescriptor *out_desc = av_pix_fmt_desc_get(outlink->format); | |
534 | char *expr; | ||
535 | int eval_w, eval_h; | ||
536 | int ret; | ||
537 | double res; | ||
538 | const AVPixFmtDescriptor *main_desc; | ||
539 | const AVFilterLink *main_link; | ||
540 | |||
541 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6416 times.
|
6416 | if (scale2ref) { |
542 | ✗ | main_link = ctx->inputs[0]; | |
543 | ✗ | main_desc = av_pix_fmt_desc_get(main_link->format); | |
544 | } | ||
545 | |||
546 | 6416 | scale->var_values[VAR_IN_W] = scale->var_values[VAR_IW] = inlink->w; | |
547 | 6416 | scale->var_values[VAR_IN_H] = scale->var_values[VAR_IH] = inlink->h; | |
548 | 6416 | scale->var_values[VAR_OUT_W] = scale->var_values[VAR_OW] = NAN; | |
549 | 6416 | scale->var_values[VAR_OUT_H] = scale->var_values[VAR_OH] = NAN; | |
550 | 6416 | scale->var_values[VAR_A] = (double) inlink->w / inlink->h; | |
551 | 12832 | scale->var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? | |
552 |
2/2✓ Branch 0 taken 2397 times.
✓ Branch 1 taken 4019 times.
|
6416 | (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1; |
553 | 6416 | scale->var_values[VAR_DAR] = scale->var_values[VAR_A] * scale->var_values[VAR_SAR]; | |
554 | 6416 | scale->var_values[VAR_HSUB] = 1 << desc->log2_chroma_w; | |
555 | 6416 | scale->var_values[VAR_VSUB] = 1 << desc->log2_chroma_h; | |
556 | 6416 | scale->var_values[VAR_OHSUB] = 1 << out_desc->log2_chroma_w; | |
557 | 6416 | scale->var_values[VAR_OVSUB] = 1 << out_desc->log2_chroma_h; | |
558 | |||
559 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6416 times.
|
6416 | if (scale2ref) { |
560 | ✗ | scale->var_values[VAR_S2R_MAIN_W] = main_link->w; | |
561 | ✗ | scale->var_values[VAR_S2R_MAIN_H] = main_link->h; | |
562 | ✗ | scale->var_values[VAR_S2R_MAIN_A] = (double) main_link->w / main_link->h; | |
563 | ✗ | scale->var_values[VAR_S2R_MAIN_SAR] = main_link->sample_aspect_ratio.num ? | |
564 | ✗ | (double) main_link->sample_aspect_ratio.num / main_link->sample_aspect_ratio.den : 1; | |
565 | ✗ | scale->var_values[VAR_S2R_MAIN_DAR] = scale->var_values[VAR_S2R_MDAR] = | |
566 | ✗ | scale->var_values[VAR_S2R_MAIN_A] * scale->var_values[VAR_S2R_MAIN_SAR]; | |
567 | ✗ | scale->var_values[VAR_S2R_MAIN_HSUB] = 1 << main_desc->log2_chroma_w; | |
568 | ✗ | scale->var_values[VAR_S2R_MAIN_VSUB] = 1 << main_desc->log2_chroma_h; | |
569 | } | ||
570 | |||
571 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6415 times.
|
6416 | if (scale->uses_ref) { |
572 | 1 | const AVFilterLink *reflink = ctx->inputs[1]; | |
573 | 1 | const AVPixFmtDescriptor *ref_desc = av_pix_fmt_desc_get(reflink->format); | |
574 | 1 | scale->var_values[VAR_REF_W] = scale->var_values[VAR_RW] = reflink->w; | |
575 | 1 | scale->var_values[VAR_REF_H] = scale->var_values[VAR_RH] = reflink->h; | |
576 | 1 | scale->var_values[VAR_REF_A] = (double) reflink->w / reflink->h; | |
577 | 2 | scale->var_values[VAR_REF_SAR] = reflink->sample_aspect_ratio.num ? | |
578 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | (double) reflink->sample_aspect_ratio.num / reflink->sample_aspect_ratio.den : 1; |
579 | 1 | scale->var_values[VAR_REF_DAR] = scale->var_values[VAR_RDAR] = | |
580 | 1 | scale->var_values[VAR_REF_A] * scale->var_values[VAR_REF_SAR]; | |
581 | 1 | scale->var_values[VAR_REF_HSUB] = 1 << ref_desc->log2_chroma_w; | |
582 | 1 | scale->var_values[VAR_REF_VSUB] = 1 << ref_desc->log2_chroma_h; | |
583 | } | ||
584 | |||
585 | 6416 | res = av_expr_eval(scale->w_pexpr, scale->var_values, NULL); | |
586 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6416 times.
|
6416 | eval_w = scale->var_values[VAR_OUT_W] = scale->var_values[VAR_OW] = (int) res == 0 ? inlink->w : (int) res; |
587 | |||
588 | 6416 | res = av_expr_eval(scale->h_pexpr, scale->var_values, NULL); | |
589 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6416 times.
|
6416 | if (isnan(res)) { |
590 | ✗ | expr = scale->h_expr; | |
591 | ✗ | ret = AVERROR(EINVAL); | |
592 | ✗ | goto fail; | |
593 | } | ||
594 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6416 times.
|
6416 | eval_h = scale->var_values[VAR_OUT_H] = scale->var_values[VAR_OH] = (int) res == 0 ? inlink->h : (int) res; |
595 | |||
596 | 6416 | res = av_expr_eval(scale->w_pexpr, scale->var_values, NULL); | |
597 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6416 times.
|
6416 | if (isnan(res)) { |
598 | ✗ | expr = scale->w_expr; | |
599 | ✗ | ret = AVERROR(EINVAL); | |
600 | ✗ | goto fail; | |
601 | } | ||
602 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6416 times.
|
6416 | eval_w = scale->var_values[VAR_OUT_W] = scale->var_values[VAR_OW] = (int) res == 0 ? inlink->w : (int) res; |
603 | |||
604 | 6416 | scale->w = eval_w; | |
605 | 6416 | scale->h = eval_h; | |
606 | |||
607 | 6416 | return 0; | |
608 | |||
609 | ✗ | fail: | |
610 | ✗ | av_log(ctx, AV_LOG_ERROR, | |
611 | "Error when evaluating the expression '%s'.\n", expr); | ||
612 | ✗ | return ret; | |
613 | } | ||
614 | |||
615 | 6416 | static int config_props(AVFilterLink *outlink) | |
616 | { | ||
617 | 6416 | AVFilterContext *ctx = outlink->src; | |
618 | 6416 | AVFilterLink *inlink0 = outlink->src->inputs[0]; | |
619 | 12832 | AVFilterLink *inlink = IS_SCALE2REF(ctx) ? | |
620 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6416 times.
|
6416 | outlink->src->inputs[1] : |
621 | 6416 | outlink->src->inputs[0]; | |
622 | 6416 | ScaleContext *scale = ctx->priv; | |
623 | 6416 | uint8_t *flags_val = NULL; | |
624 | 6416 | double w_adj = 1.0; | |
625 | int ret; | ||
626 | |||
627 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6416 times.
|
6416 | if ((ret = scale_eval_dimensions(ctx)) < 0) |
628 | ✗ | goto fail; | |
629 | |||
630 | 6416 | outlink->w = scale->w; | |
631 | 6416 | outlink->h = scale->h; | |
632 | |||
633 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6416 times.
|
6416 | if (scale->reset_sar) |
634 | ✗ | w_adj = IS_SCALE2REF(ctx) ? scale->var_values[VAR_S2R_MAIN_SAR] : | |
635 | scale->var_values[VAR_SAR]; | ||
636 | |||
637 | 6416 | ret = ff_scale_adjust_dimensions(inlink, &outlink->w, &outlink->h, | |
638 | scale->force_original_aspect_ratio, | ||
639 | scale->force_divisible_by, w_adj); | ||
640 | |||
641 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6416 times.
|
6416 | if (ret < 0) |
642 | ✗ | goto fail; | |
643 | |||
644 | if (outlink->w > INT_MAX || | ||
645 | outlink->h > INT_MAX || | ||
646 | (outlink->h * inlink->w) > INT_MAX || | ||
647 | (outlink->w * inlink->h) > INT_MAX) | ||
648 | av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n"); | ||
649 | |||
650 | /* TODO: make algorithm configurable */ | ||
651 | |||
652 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6416 times.
|
6416 | if (scale->reset_sar) |
653 | ✗ | outlink->sample_aspect_ratio = (AVRational){1, 1}; | |
654 |
2/2✓ Branch 0 taken 2397 times.
✓ Branch 1 taken 4019 times.
|
6416 | else if (inlink0->sample_aspect_ratio.num){ |
655 | 2397 | outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h * inlink0->w, outlink->w * inlink0->h}, inlink0->sample_aspect_ratio); | |
656 | } else | ||
657 | 4019 | outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio; | |
658 | |||
659 | 6416 | av_opt_get(scale->sws, "sws_flags", 0, &flags_val); | |
660 | 19248 | av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d fmt:%s csp:%s range:%s sar:%d/%d -> w:%d h:%d fmt:%s csp:%s range:%s sar:%d/%d flags:%s\n", | |
661 | 6416 | inlink ->w, inlink ->h, av_get_pix_fmt_name( inlink->format), | |
662 | av_color_space_name(inlink->colorspace), av_color_range_name(inlink->color_range), | ||
663 | inlink->sample_aspect_ratio.num, inlink->sample_aspect_ratio.den, | ||
664 | 6416 | outlink->w, outlink->h, av_get_pix_fmt_name(outlink->format), | |
665 | av_color_space_name(outlink->colorspace), av_color_range_name(outlink->color_range), | ||
666 | outlink->sample_aspect_ratio.num, outlink->sample_aspect_ratio.den, | ||
667 | flags_val); | ||
668 | 6416 | av_freep(&flags_val); | |
669 | |||
670 |
4/4✓ Branch 0 taken 5970 times.
✓ Branch 1 taken 446 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 5960 times.
|
6416 | if (inlink->w != outlink->w || inlink->h != outlink->h) { |
671 | 456 | av_frame_side_data_remove_by_props(&outlink->side_data, &outlink->nb_side_data, | |
672 | AV_SIDE_DATA_PROP_SIZE_DEPENDENT); | ||
673 | } | ||
674 | |||
675 |
2/4✓ Branch 0 taken 6416 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6416 times.
|
6416 | if (scale->in_primaries != scale->out_primaries || scale->in_transfer != scale->out_transfer) { |
676 | ✗ | av_frame_side_data_remove_by_props(&outlink->side_data, &outlink->nb_side_data, | |
677 | AV_SIDE_DATA_PROP_COLOR_DEPENDENT); | ||
678 | } | ||
679 | |||
680 |
1/2✓ Branch 0 taken 6416 times.
✗ Branch 1 not taken.
|
6416 | if (!IS_SCALE2REF(ctx)) { |
681 | 6416 | ff_framesync_uninit(&scale->fs); | |
682 | 6416 | ret = ff_framesync_init(&scale->fs, ctx, ctx->nb_inputs); | |
683 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6416 times.
|
6416 | if (ret < 0) |
684 | ✗ | return ret; | |
685 | 6416 | scale->fs.on_event = do_scale; | |
686 | 6416 | scale->fs.in[0].time_base = ctx->inputs[0]->time_base; | |
687 | 6416 | scale->fs.in[0].sync = 1; | |
688 | 6416 | scale->fs.in[0].before = EXT_STOP; | |
689 | 6416 | scale->fs.in[0].after = EXT_STOP; | |
690 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6415 times.
|
6416 | if (scale->uses_ref) { |
691 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | av_assert0(ctx->nb_inputs == 2); |
692 | 1 | scale->fs.in[1].time_base = ctx->inputs[1]->time_base; | |
693 | 1 | scale->fs.in[1].sync = 0; | |
694 | 1 | scale->fs.in[1].before = EXT_NULL; | |
695 | 1 | scale->fs.in[1].after = EXT_INFINITY; | |
696 | } | ||
697 | |||
698 | 6416 | ret = ff_framesync_configure(&scale->fs); | |
699 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6416 times.
|
6416 | if (ret < 0) |
700 | ✗ | return ret; | |
701 | } | ||
702 | |||
703 | 6416 | return 0; | |
704 | |||
705 | ✗ | fail: | |
706 | ✗ | return ret; | |
707 | } | ||
708 | |||
709 | ✗ | static int config_props_ref(AVFilterLink *outlink) | |
710 | { | ||
711 | ✗ | AVFilterLink *inlink = outlink->src->inputs[1]; | |
712 | ✗ | FilterLink *il = ff_filter_link(inlink); | |
713 | ✗ | FilterLink *ol = ff_filter_link(outlink); | |
714 | |||
715 | ✗ | outlink->w = inlink->w; | |
716 | ✗ | outlink->h = inlink->h; | |
717 | ✗ | outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; | |
718 | ✗ | outlink->time_base = inlink->time_base; | |
719 | ✗ | ol->frame_rate = il->frame_rate; | |
720 | ✗ | outlink->colorspace = inlink->colorspace; | |
721 | ✗ | outlink->color_range = inlink->color_range; | |
722 | |||
723 | ✗ | return 0; | |
724 | } | ||
725 | |||
726 | ✗ | static int request_frame(AVFilterLink *outlink) | |
727 | { | ||
728 | ✗ | return ff_request_frame(outlink->src->inputs[0]); | |
729 | } | ||
730 | |||
731 | ✗ | static int request_frame_ref(AVFilterLink *outlink) | |
732 | { | ||
733 | ✗ | return ff_request_frame(outlink->src->inputs[1]); | |
734 | } | ||
735 | |||
736 | /* Takes over ownership of *frame_in, passes ownership of *frame_out to caller */ | ||
737 | 103538 | static int scale_frame(AVFilterLink *link, AVFrame **frame_in, | |
738 | AVFrame **frame_out) | ||
739 | { | ||
740 | 103538 | FilterLink *inl = ff_filter_link(link); | |
741 | 103538 | AVFilterContext *ctx = link->dst; | |
742 | 103538 | ScaleContext *scale = ctx->priv; | |
743 | 103538 | AVFilterLink *outlink = ctx->outputs[0]; | |
744 | 103538 | AVFrame *out, *in = *frame_in; | |
745 | 103538 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); | |
746 | char buf[32]; | ||
747 | int ret, flags_orig, frame_changed; | ||
748 | |||
749 | 103538 | *frame_in = NULL; | |
750 | |||
751 | 310613 | frame_changed = in->width != link->w || | |
752 |
1/2✓ Branch 0 taken 103537 times.
✗ Branch 1 not taken.
|
103537 | in->height != link->h || |
753 |
1/2✓ Branch 0 taken 103537 times.
✗ Branch 1 not taken.
|
103537 | in->format != link->format || |
754 |
1/2✓ Branch 0 taken 103537 times.
✗ Branch 1 not taken.
|
103537 | in->sample_aspect_ratio.den != link->sample_aspect_ratio.den || |
755 |
1/2✓ Branch 0 taken 103537 times.
✗ Branch 1 not taken.
|
103537 | in->sample_aspect_ratio.num != link->sample_aspect_ratio.num || |
756 |
4/4✓ Branch 0 taken 103537 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 103522 times.
✓ Branch 3 taken 15 times.
|
310597 | in->colorspace != link->colorspace || |
757 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 103520 times.
|
103522 | in->color_range != link->color_range; |
758 | |||
759 |
3/4✓ Branch 0 taken 103538 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 103520 times.
|
103538 | if (scale->eval_mode == EVAL_MODE_FRAME || frame_changed) { |
760 | 18 | unsigned vars_w[VARS_NB] = { 0 }, vars_h[VARS_NB] = { 0 }; | |
761 | |||
762 | 18 | av_expr_count_vars(scale->w_pexpr, vars_w, VARS_NB); | |
763 | 18 | av_expr_count_vars(scale->h_pexpr, vars_h, VARS_NB); | |
764 | |||
765 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
18 | if (scale->eval_mode == EVAL_MODE_FRAME && |
766 | ✗ | !frame_changed && | |
767 | ✗ | !IS_SCALE2REF(ctx) && | |
768 | ✗ | !(vars_w[VAR_N] || vars_w[VAR_T]) && | |
769 | ✗ | !(vars_h[VAR_N] || vars_h[VAR_T]) && | |
770 | ✗ | scale->w && scale->h) | |
771 | ✗ | goto scale; | |
772 | |||
773 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (scale->eval_mode == EVAL_MODE_INIT) { |
774 | 18 | snprintf(buf, sizeof(buf) - 1, "%d", scale->w); | |
775 | 18 | av_opt_set(scale, "w", buf, 0); | |
776 | 18 | snprintf(buf, sizeof(buf) - 1, "%d", scale->h); | |
777 | 18 | av_opt_set(scale, "h", buf, 0); | |
778 | |||
779 | 18 | ret = scale_parse_expr(ctx, NULL, &scale->w_pexpr, "width", scale->w_expr); | |
780 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (ret < 0) |
781 | ✗ | goto err; | |
782 | |||
783 | 18 | ret = scale_parse_expr(ctx, NULL, &scale->h_pexpr, "height", scale->h_expr); | |
784 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (ret < 0) |
785 | ✗ | goto err; | |
786 | } | ||
787 | |||
788 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (IS_SCALE2REF(ctx)) { |
789 | ✗ | scale->var_values[VAR_S2R_MAIN_N] = inl->frame_count_out; | |
790 | ✗ | scale->var_values[VAR_S2R_MAIN_T] = TS2T(in->pts, link->time_base); | |
791 | } else { | ||
792 | 18 | scale->var_values[VAR_N] = inl->frame_count_out; | |
793 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | scale->var_values[VAR_T] = TS2T(in->pts, link->time_base); |
794 | } | ||
795 | |||
796 | 18 | link->dst->inputs[0]->format = in->format; | |
797 | 18 | link->dst->inputs[0]->w = in->width; | |
798 | 18 | link->dst->inputs[0]->h = in->height; | |
799 | 18 | link->dst->inputs[0]->colorspace = in->colorspace; | |
800 | 18 | link->dst->inputs[0]->color_range = in->color_range; | |
801 | |||
802 | 18 | link->dst->inputs[0]->sample_aspect_ratio.den = in->sample_aspect_ratio.den; | |
803 | 18 | link->dst->inputs[0]->sample_aspect_ratio.num = in->sample_aspect_ratio.num; | |
804 | |||
805 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
|
18 | if ((ret = config_props(outlink)) < 0) |
806 | ✗ | goto err; | |
807 | } | ||
808 | |||
809 | 103520 | scale: | |
810 | 103538 | scale->hsub = desc->log2_chroma_w; | |
811 | 103538 | scale->vsub = desc->log2_chroma_h; | |
812 | |||
813 | 103538 | out = ff_get_video_buffer(outlink, outlink->w, outlink->h); | |
814 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 103538 times.
|
103538 | if (!out) { |
815 | ✗ | ret = AVERROR(ENOMEM); | |
816 | ✗ | goto err; | |
817 | } | ||
818 | |||
819 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 103536 times.
|
103538 | if (scale->in_color_matrix != -1) |
820 | 2 | in->colorspace = scale->in_color_matrix; | |
821 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 103538 times.
|
103538 | if (scale->in_primaries != -1) |
822 | ✗ | in->color_primaries = scale->in_primaries; | |
823 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 103538 times.
|
103538 | if (scale->in_transfer != -1) |
824 | ✗ | in->color_trc = scale->in_transfer; | |
825 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 103536 times.
|
103538 | if (scale->in_range != AVCOL_RANGE_UNSPECIFIED) |
826 | 2 | in->color_range = scale->in_range; | |
827 | 103538 | in->chroma_location = scale->in_chroma_loc; | |
828 | |||
829 | 103538 | flags_orig = in->flags; | |
830 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 103538 times.
|
103538 | if (scale->interlaced > 0) |
831 | ✗ | in->flags |= AV_FRAME_FLAG_INTERLACED; | |
832 |
1/2✓ Branch 0 taken 103538 times.
✗ Branch 1 not taken.
|
103538 | else if (!scale->interlaced) |
833 | 103538 | in->flags &= ~AV_FRAME_FLAG_INTERLACED; | |
834 | |||
835 | 103538 | av_frame_copy_props(out, in); | |
836 | 103538 | out->width = outlink->w; | |
837 | 103538 | out->height = outlink->h; | |
838 | 103538 | out->color_range = outlink->color_range; | |
839 | 103538 | out->colorspace = outlink->colorspace; | |
840 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 103513 times.
|
103538 | if (scale->out_chroma_loc != AVCHROMA_LOC_UNSPECIFIED) |
841 | 25 | out->chroma_location = scale->out_chroma_loc; | |
842 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 103538 times.
|
103538 | if (scale->out_primaries != -1) |
843 | ✗ | out->color_primaries = scale->out_primaries; | |
844 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 103538 times.
|
103538 | if (scale->out_transfer != -1) |
845 | ✗ | out->color_trc = scale->out_transfer; | |
846 | |||
847 |
4/4✓ Branch 0 taken 97636 times.
✓ Branch 1 taken 5902 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 97623 times.
|
103538 | if (out->width != in->width || out->height != in->height) { |
848 | 5915 | av_frame_side_data_remove_by_props(&out->side_data, &out->nb_side_data, | |
849 | AV_SIDE_DATA_PROP_SIZE_DEPENDENT); | ||
850 | } | ||
851 | |||
852 |
2/4✓ Branch 0 taken 103538 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 103538 times.
|
103538 | if (in->color_primaries != out->color_primaries || in->color_trc != out->color_trc) { |
853 | ✗ | av_frame_side_data_remove_by_props(&out->side_data, &out->nb_side_data, | |
854 | AV_SIDE_DATA_PROP_COLOR_DEPENDENT); | ||
855 | } | ||
856 | |||
857 | 103538 | av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den, | |
858 | 103538 | (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w, | |
859 | 103538 | (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h, | |
860 | INT_MAX); | ||
861 | |||
862 |
2/2✓ Branch 1 taken 4754 times.
✓ Branch 2 taken 98784 times.
|
103538 | if (sws_is_noop(out, in)) { |
863 | 4754 | av_frame_free(&out); | |
864 | 4754 | in->flags = flags_orig; | |
865 | 4754 | *frame_out = in; | |
866 | 4754 | return 0; | |
867 | } | ||
868 | |||
869 |
2/2✓ Branch 0 taken 581 times.
✓ Branch 1 taken 98203 times.
|
98784 | if (out->format == AV_PIX_FMT_PAL8) { |
870 | 581 | out->format = AV_PIX_FMT_BGR8; | |
871 | 581 | avpriv_set_systematic_pal2((uint32_t*) out->data[1], out->format); | |
872 | } | ||
873 | |||
874 | 98784 | ret = sws_scale_frame(scale->sws, out, in); | |
875 | 98784 | av_frame_free(&in); | |
876 | 98784 | out->flags = flags_orig; | |
877 | 98784 | out->format = outlink->format; /* undo PAL8 handling */ | |
878 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 98784 times.
|
98784 | if (ret < 0) |
879 | ✗ | av_frame_free(&out); | |
880 | 98784 | *frame_out = out; | |
881 | 98784 | return ret; | |
882 | |||
883 | ✗ | err: | |
884 | ✗ | av_frame_free(&in); | |
885 | ✗ | return ret; | |
886 | } | ||
887 | |||
888 | 103538 | static int do_scale(FFFrameSync *fs) | |
889 | { | ||
890 | 103538 | AVFilterContext *ctx = fs->parent; | |
891 | 103538 | ScaleContext *scale = ctx->priv; | |
892 | 103538 | AVFilterLink *outlink = ctx->outputs[0]; | |
893 | 103538 | AVFrame *out, *in = NULL, *ref = NULL; | |
894 | 103538 | int ret = 0, frame_changed; | |
895 | |||
896 | 103538 | ret = ff_framesync_get_frame(fs, 0, &in, 1); | |
897 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 103538 times.
|
103538 | if (ret < 0) |
898 | ✗ | goto err; | |
899 | |||
900 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 103533 times.
|
103538 | if (scale->uses_ref) { |
901 | 5 | ret = ff_framesync_get_frame(fs, 1, &ref, 0); | |
902 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (ret < 0) |
903 | ✗ | goto err; | |
904 | } | ||
905 | |||
906 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 103533 times.
|
103538 | if (ref) { |
907 | 5 | AVFilterLink *reflink = ctx->inputs[1]; | |
908 | 5 | FilterLink *rl = ff_filter_link(reflink); | |
909 | |||
910 | 15 | frame_changed = ref->width != reflink->w || | |
911 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | ref->height != reflink->h || |
912 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | ref->format != reflink->format || |
913 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | ref->sample_aspect_ratio.den != reflink->sample_aspect_ratio.den || |
914 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | ref->sample_aspect_ratio.num != reflink->sample_aspect_ratio.num || |
915 |
2/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
15 | ref->colorspace != reflink->colorspace || |
916 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | ref->color_range != reflink->color_range; |
917 | |||
918 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (frame_changed) { |
919 | ✗ | reflink->format = ref->format; | |
920 | ✗ | reflink->w = ref->width; | |
921 | ✗ | reflink->h = ref->height; | |
922 | ✗ | reflink->sample_aspect_ratio.num = ref->sample_aspect_ratio.num; | |
923 | ✗ | reflink->sample_aspect_ratio.den = ref->sample_aspect_ratio.den; | |
924 | ✗ | reflink->colorspace = ref->colorspace; | |
925 | ✗ | reflink->color_range = ref->color_range; | |
926 | |||
927 | ✗ | ret = config_props(outlink); | |
928 | ✗ | if (ret < 0) | |
929 | ✗ | goto err; | |
930 | } | ||
931 | |||
932 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (scale->eval_mode == EVAL_MODE_FRAME) { |
933 | ✗ | scale->var_values[VAR_REF_N] = rl->frame_count_out; | |
934 | ✗ | scale->var_values[VAR_REF_T] = TS2T(ref->pts, reflink->time_base); | |
935 | } | ||
936 | } | ||
937 | |||
938 | 103538 | ret = scale_frame(ctx->inputs[0], &in, &out); | |
939 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 103538 times.
|
103538 | if (ret < 0) |
940 | ✗ | goto err; | |
941 | |||
942 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 103538 times.
|
103538 | av_assert0(out); |
943 | 103538 | out->pts = av_rescale_q(fs->pts, fs->time_base, outlink->time_base); | |
944 | 103538 | return ff_filter_frame(outlink, out); | |
945 | |||
946 | ✗ | err: | |
947 | ✗ | av_frame_free(&in); | |
948 | ✗ | return ret; | |
949 | } | ||
950 | |||
951 | ✗ | static int filter_frame(AVFilterLink *link, AVFrame *in) | |
952 | { | ||
953 | ✗ | AVFilterContext *ctx = link->dst; | |
954 | ✗ | AVFilterLink *outlink = ctx->outputs[0]; | |
955 | AVFrame *out; | ||
956 | int ret; | ||
957 | |||
958 | ✗ | ret = scale_frame(link, &in, &out); | |
959 | ✗ | if (out) | |
960 | ✗ | return ff_filter_frame(outlink, out); | |
961 | |||
962 | ✗ | return ret; | |
963 | } | ||
964 | |||
965 | ✗ | static int filter_frame_ref(AVFilterLink *link, AVFrame *in) | |
966 | { | ||
967 | ✗ | FilterLink *l = ff_filter_link(link); | |
968 | ✗ | ScaleContext *scale = link->dst->priv; | |
969 | ✗ | AVFilterLink *outlink = link->dst->outputs[1]; | |
970 | int frame_changed; | ||
971 | |||
972 | ✗ | frame_changed = in->width != link->w || | |
973 | ✗ | in->height != link->h || | |
974 | ✗ | in->format != link->format || | |
975 | ✗ | in->sample_aspect_ratio.den != link->sample_aspect_ratio.den || | |
976 | ✗ | in->sample_aspect_ratio.num != link->sample_aspect_ratio.num || | |
977 | ✗ | in->colorspace != link->colorspace || | |
978 | ✗ | in->color_range != link->color_range; | |
979 | |||
980 | ✗ | if (frame_changed) { | |
981 | ✗ | link->format = in->format; | |
982 | ✗ | link->w = in->width; | |
983 | ✗ | link->h = in->height; | |
984 | ✗ | link->sample_aspect_ratio.num = in->sample_aspect_ratio.num; | |
985 | ✗ | link->sample_aspect_ratio.den = in->sample_aspect_ratio.den; | |
986 | ✗ | link->colorspace = in->colorspace; | |
987 | ✗ | link->color_range = in->color_range; | |
988 | |||
989 | ✗ | config_props_ref(outlink); | |
990 | } | ||
991 | |||
992 | ✗ | if (scale->eval_mode == EVAL_MODE_FRAME) { | |
993 | ✗ | scale->var_values[VAR_N] = l->frame_count_out; | |
994 | ✗ | scale->var_values[VAR_T] = TS2T(in->pts, link->time_base); | |
995 | } | ||
996 | |||
997 | ✗ | return ff_filter_frame(outlink, in); | |
998 | } | ||
999 | |||
1000 | ✗ | static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, | |
1001 | char *res, int res_len, int flags) | ||
1002 | { | ||
1003 | ✗ | ScaleContext *scale = ctx->priv; | |
1004 | char *str_expr; | ||
1005 | AVExpr **pexpr_ptr; | ||
1006 | int ret, w, h; | ||
1007 | |||
1008 | ✗ | w = !strcmp(cmd, "width") || !strcmp(cmd, "w"); | |
1009 | ✗ | h = !strcmp(cmd, "height") || !strcmp(cmd, "h"); | |
1010 | |||
1011 | ✗ | if (w || h) { | |
1012 | ✗ | str_expr = w ? scale->w_expr : scale->h_expr; | |
1013 | ✗ | pexpr_ptr = w ? &scale->w_pexpr : &scale->h_pexpr; | |
1014 | |||
1015 | ✗ | ret = scale_parse_expr(ctx, str_expr, pexpr_ptr, cmd, args); | |
1016 | } else | ||
1017 | ✗ | ret = AVERROR(ENOSYS); | |
1018 | |||
1019 | ✗ | if (ret < 0) | |
1020 | ✗ | av_log(ctx, AV_LOG_ERROR, "Failed to process command. Continuing with existing parameters.\n"); | |
1021 | |||
1022 | ✗ | return ret; | |
1023 | } | ||
1024 | |||
1025 | 206064 | static int activate(AVFilterContext *ctx) | |
1026 | { | ||
1027 | 206064 | ScaleContext *scale = ctx->priv; | |
1028 | 206064 | return ff_framesync_activate(&scale->fs); | |
1029 | } | ||
1030 | |||
1031 | ✗ | static const AVClass *child_class_iterate(void **iter) | |
1032 | { | ||
1033 | ✗ | switch ((uintptr_t) *iter) { | |
1034 | ✗ | case 0: | |
1035 | ✗ | *iter = (void*)(uintptr_t) 1; | |
1036 | ✗ | return sws_get_class(); | |
1037 | ✗ | case 1: | |
1038 | ✗ | *iter = (void*)(uintptr_t) 2; | |
1039 | ✗ | return &ff_framesync_class; | |
1040 | } | ||
1041 | |||
1042 | ✗ | return NULL; | |
1043 | } | ||
1044 | |||
1045 | 24136 | static void *child_next(void *obj, void *prev) | |
1046 | { | ||
1047 | 24136 | ScaleContext *s = obj; | |
1048 |
2/2✓ Branch 0 taken 12670 times.
✓ Branch 1 taken 11466 times.
|
24136 | if (!prev) |
1049 | 12670 | return s->sws; | |
1050 |
2/2✓ Branch 0 taken 5733 times.
✓ Branch 1 taken 5733 times.
|
11466 | if (prev == s->sws) |
1051 | 5733 | return &s->fs; | |
1052 | 5733 | return NULL; | |
1053 | } | ||
1054 | |||
1055 | #define OFFSET(x) offsetof(ScaleContext, x) | ||
1056 | #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM | ||
1057 | #define TFLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM | ||
1058 | |||
1059 | static const AVOption scale_options[] = { | ||
1060 | { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, .flags = TFLAGS }, | ||
1061 | { "width", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, .flags = TFLAGS }, | ||
1062 | { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, .flags = TFLAGS }, | ||
1063 | { "height","Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, .flags = TFLAGS }, | ||
1064 | { "flags", "Flags to pass to libswscale", OFFSET(flags_str), AV_OPT_TYPE_STRING, { .str = "" }, .flags = FLAGS }, | ||
1065 | { "interl", "set interlacing", OFFSET(interlaced), AV_OPT_TYPE_BOOL, {.i64 = 0 }, -1, 1, FLAGS }, | ||
1066 | { "size", "set video size", OFFSET(size_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, .flags = FLAGS }, | ||
1067 | { "s", "set video size", OFFSET(size_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, .flags = FLAGS }, | ||
1068 | { "in_color_matrix", "set input YCbCr type", OFFSET(in_color_matrix), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, AVCOL_SPC_NB-1, .flags = FLAGS, .unit = "color" }, | ||
1069 | { "out_color_matrix", "set output YCbCr type", OFFSET(out_color_matrix), AV_OPT_TYPE_INT, { .i64 = AVCOL_SPC_UNSPECIFIED }, 0, AVCOL_SPC_NB-1, .flags = FLAGS, .unit = "color"}, | ||
1070 | { "auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, .unit = "color" }, | ||
1071 | { "bt601", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT470BG}, 0, 0, FLAGS, .unit = "color" }, | ||
1072 | { "bt470", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT470BG}, 0, 0, FLAGS, .unit = "color" }, | ||
1073 | { "smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT470BG}, 0, 0, FLAGS, .unit = "color" }, | ||
1074 | { "bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT709}, 0, 0, FLAGS, .unit = "color" }, | ||
1075 | { "fcc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_FCC}, 0, 0, FLAGS, .unit = "color" }, | ||
1076 | { "smpte240m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_SMPTE240M}, 0, 0, FLAGS, .unit = "color" }, | ||
1077 | { "bt2020", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT2020_NCL}, 0, 0, FLAGS, .unit = "color" }, | ||
1078 | { "in_range", "set input color range", OFFSET( in_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, 2, FLAGS, .unit = "range" }, | ||
1079 | { "out_range", "set output color range", OFFSET(out_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, 2, FLAGS, .unit = "range" }, | ||
1080 | { "auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_UNSPECIFIED }, 0, 0, FLAGS, .unit = "range" }, | ||
1081 | { "unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_UNSPECIFIED }, 0, 0, FLAGS, .unit = "range" }, | ||
1082 | { "full", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, FLAGS, .unit = "range" }, | ||
1083 | { "limited", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_MPEG}, 0, 0, FLAGS, .unit = "range" }, | ||
1084 | { "jpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, FLAGS, .unit = "range" }, | ||
1085 | { "mpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_MPEG}, 0, 0, FLAGS, .unit = "range" }, | ||
1086 | { "tv", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_MPEG}, 0, 0, FLAGS, .unit = "range" }, | ||
1087 | { "pc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, FLAGS, .unit = "range" }, | ||
1088 | { "in_chroma_loc", "set input chroma sample location", OFFSET(in_chroma_loc), AV_OPT_TYPE_INT, { .i64 = AVCHROMA_LOC_UNSPECIFIED }, 0, AVCHROMA_LOC_NB-1, .flags = FLAGS, .unit = "chroma_loc" }, | ||
1089 | { "out_chroma_loc", "set output chroma sample location", OFFSET(out_chroma_loc), AV_OPT_TYPE_INT, { .i64 = AVCHROMA_LOC_UNSPECIFIED }, 0, AVCHROMA_LOC_NB-1, .flags = FLAGS, .unit = "chroma_loc" }, | ||
1090 | {"auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_UNSPECIFIED}, 0, 0, FLAGS, .unit = "chroma_loc"}, | ||
1091 | {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_UNSPECIFIED}, 0, 0, FLAGS, .unit = "chroma_loc"}, | ||
1092 | {"left", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_LEFT}, 0, 0, FLAGS, .unit = "chroma_loc"}, | ||
1093 | {"center", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_CENTER}, 0, 0, FLAGS, .unit = "chroma_loc"}, | ||
1094 | {"topleft", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_TOPLEFT}, 0, 0, FLAGS, .unit = "chroma_loc"}, | ||
1095 | {"top", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_TOP}, 0, 0, FLAGS, .unit = "chroma_loc"}, | ||
1096 | {"bottomleft", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_BOTTOMLEFT}, 0, 0, FLAGS, .unit = "chroma_loc"}, | ||
1097 | {"bottom", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_BOTTOM}, 0, 0, FLAGS, .unit = "chroma_loc"}, | ||
1098 | { "in_primaries", "set input primaries", OFFSET(in_primaries), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, AVCOL_PRI_NB-1, .flags = FLAGS, .unit = "primaries" }, | ||
1099 | { "out_primaries", "set output primaries", OFFSET(out_primaries), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, AVCOL_PRI_NB-1, .flags = FLAGS, .unit = "primaries"}, | ||
1100 | {"auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, .unit = "primaries"}, | ||
1101 | {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT709}, 0, 0, FLAGS, .unit = "primaries"}, | ||
1102 | {"bt470m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT470M}, 0, 0, FLAGS, .unit = "primaries"}, | ||
1103 | {"bt470bg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT470BG}, 0, 0, FLAGS, .unit = "primaries"}, | ||
1104 | {"smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE170M}, 0, 0, FLAGS, .unit = "primaries"}, | ||
1105 | {"smpte240m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE240M}, 0, 0, FLAGS, .unit = "primaries"}, | ||
1106 | {"film", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_FILM}, 0, 0, FLAGS, .unit = "primaries"}, | ||
1107 | {"bt2020", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT2020}, 0, 0, FLAGS, .unit = "primaries"}, | ||
1108 | {"smpte428", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE428}, 0, 0, FLAGS, .unit = "primaries"}, | ||
1109 | {"smpte431", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE431}, 0, 0, FLAGS, .unit = "primaries"}, | ||
1110 | {"smpte432", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE432}, 0, 0, FLAGS, .unit = "primaries"}, | ||
1111 | {"jedec-p22", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_JEDEC_P22}, 0, 0, FLAGS, .unit = "primaries"}, | ||
1112 | {"ebu3213", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_EBU3213}, 0, 0, FLAGS, .unit = "primaries"}, | ||
1113 | { "in_transfer", "set output color transfer", OFFSET(in_transfer), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, AVCOL_TRC_NB-1, .flags = FLAGS, .unit = "transfer"}, | ||
1114 | {"out_transfer", "set output color transfer", OFFSET(out_transfer), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, AVCOL_TRC_NB-1, .flags = FLAGS, .unit = "transfer"}, | ||
1115 | {"auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1116 | {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT709}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1117 | {"bt470m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_GAMMA22}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1118 | {"gamma22", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_GAMMA22}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1119 | {"bt470bg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_GAMMA28}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1120 | {"gamma28", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_GAMMA28}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1121 | {"smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE170M}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1122 | {"smpte240m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE240M}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1123 | {"linear", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_LINEAR}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1124 | {"iec61966-2-1", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_IEC61966_2_1}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1125 | {"srgb", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_IEC61966_2_1}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1126 | {"iec61966-2-4", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_IEC61966_2_4}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1127 | {"xvycc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_IEC61966_2_4}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1128 | {"bt1361e", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT1361_ECG}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1129 | {"bt2020-10", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT2020_10}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1130 | {"bt2020-12", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT2020_12}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1131 | {"smpte2084", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE2084}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1132 | {"smpte428", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE428}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1133 | {"arib-std-b67", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_ARIB_STD_B67}, 0, 0, FLAGS, .unit = "transfer"}, | ||
1134 | { "in_v_chr_pos", "input vertical chroma position in luma grid/256" , OFFSET(in_v_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513}, -513, 512, FLAGS }, | ||
1135 | { "in_h_chr_pos", "input horizontal chroma position in luma grid/256", OFFSET(in_h_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513}, -513, 512, FLAGS }, | ||
1136 | { "out_v_chr_pos", "output vertical chroma position in luma grid/256" , OFFSET(out_v_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513}, -513, 512, FLAGS }, | ||
1137 | { "out_h_chr_pos", "output horizontal chroma position in luma grid/256", OFFSET(out_h_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513}, -513, 512, FLAGS }, | ||
1138 | { "force_original_aspect_ratio", "decrease or increase w/h if necessary to keep the original AR", OFFSET(force_original_aspect_ratio), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 2, FLAGS, .unit = "force_oar" }, | ||
1139 | { "disable", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, FLAGS, .unit = "force_oar" }, | ||
1140 | { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, .unit = "force_oar" }, | ||
1141 | { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, .unit = "force_oar" }, | ||
1142 | { "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1}, 1, 256, FLAGS }, | ||
1143 | { "reset_sar", "reset SAR to 1 and scale to square pixels if scaling proportionally", OFFSET(reset_sar), AV_OPT_TYPE_BOOL, { .i64 = 0}, 0, 1, FLAGS }, | ||
1144 | { "param0", "Scaler param 0", OFFSET(param[0]), AV_OPT_TYPE_DOUBLE, { .dbl = DBL_MAX }, -DBL_MAX, DBL_MAX, FLAGS }, | ||
1145 | { "param1", "Scaler param 1", OFFSET(param[1]), AV_OPT_TYPE_DOUBLE, { .dbl = DBL_MAX }, -DBL_MAX, DBL_MAX, FLAGS }, | ||
1146 | { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, {.i64 = EVAL_MODE_INIT}, 0, EVAL_MODE_NB-1, FLAGS, .unit = "eval" }, | ||
1147 | { "init", "eval expressions once during initialization", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_INIT}, .flags = FLAGS, .unit = "eval" }, | ||
1148 | { "frame", "eval expressions during initialization and per-frame", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = FLAGS, .unit = "eval" }, | ||
1149 | { NULL } | ||
1150 | }; | ||
1151 | |||
1152 | static const AVClass scale_class = { | ||
1153 | .class_name = "scale", | ||
1154 | .item_name = av_default_item_name, | ||
1155 | .option = scale_options, | ||
1156 | .version = LIBAVUTIL_VERSION_INT, | ||
1157 | .category = AV_CLASS_CATEGORY_FILTER, | ||
1158 | .child_class_iterate = child_class_iterate, | ||
1159 | .child_next = child_next, | ||
1160 | }; | ||
1161 | |||
1162 | static const AVFilterPad avfilter_vf_scale_inputs[] = { | ||
1163 | { | ||
1164 | .name = "default", | ||
1165 | .type = AVMEDIA_TYPE_VIDEO, | ||
1166 | }, | ||
1167 | }; | ||
1168 | |||
1169 | static const AVFilterPad avfilter_vf_scale_outputs[] = { | ||
1170 | { | ||
1171 | .name = "default", | ||
1172 | .type = AVMEDIA_TYPE_VIDEO, | ||
1173 | .config_props = config_props, | ||
1174 | }, | ||
1175 | }; | ||
1176 | |||
1177 | const FFFilter ff_vf_scale = { | ||
1178 | .p.name = "scale", | ||
1179 | .p.description = NULL_IF_CONFIG_SMALL("Scale the input video size and/or convert the image format."), | ||
1180 | .p.priv_class = &scale_class, | ||
1181 | .p.flags = AVFILTER_FLAG_DYNAMIC_INPUTS, | ||
1182 | .preinit = preinit, | ||
1183 | .init = init, | ||
1184 | .uninit = uninit, | ||
1185 | .priv_size = sizeof(ScaleContext), | ||
1186 | FILTER_INPUTS(avfilter_vf_scale_inputs), | ||
1187 | FILTER_OUTPUTS(avfilter_vf_scale_outputs), | ||
1188 | FILTER_QUERY_FUNC2(query_formats), | ||
1189 | .activate = activate, | ||
1190 | .process_command = process_command, | ||
1191 | }; | ||
1192 | |||
1193 | ✗ | static const AVClass *scale2ref_child_class_iterate(void **iter) | |
1194 | { | ||
1195 | ✗ | const AVClass *c = *iter ? NULL : sws_get_class(); | |
1196 | ✗ | *iter = (void*)(uintptr_t)c; | |
1197 | ✗ | return c; | |
1198 | } | ||
1199 | |||
1200 | ✗ | static void *scale2ref_child_next(void *obj, void *prev) | |
1201 | { | ||
1202 | ✗ | ScaleContext *s = obj; | |
1203 | ✗ | if (!prev) | |
1204 | ✗ | return s->sws; | |
1205 | ✗ | return NULL; | |
1206 | } | ||
1207 | |||
1208 | static const AVClass scale2ref_class = { | ||
1209 | .class_name = "scale(2ref)", | ||
1210 | .item_name = av_default_item_name, | ||
1211 | .option = scale_options, | ||
1212 | .version = LIBAVUTIL_VERSION_INT, | ||
1213 | .category = AV_CLASS_CATEGORY_FILTER, | ||
1214 | .child_class_iterate = scale2ref_child_class_iterate, | ||
1215 | .child_next = scale2ref_child_next, | ||
1216 | }; | ||
1217 | |||
1218 | static const AVFilterPad avfilter_vf_scale2ref_inputs[] = { | ||
1219 | { | ||
1220 | .name = "default", | ||
1221 | .type = AVMEDIA_TYPE_VIDEO, | ||
1222 | .filter_frame = filter_frame, | ||
1223 | }, | ||
1224 | { | ||
1225 | .name = "ref", | ||
1226 | .type = AVMEDIA_TYPE_VIDEO, | ||
1227 | .filter_frame = filter_frame_ref, | ||
1228 | }, | ||
1229 | }; | ||
1230 | |||
1231 | static const AVFilterPad avfilter_vf_scale2ref_outputs[] = { | ||
1232 | { | ||
1233 | .name = "default", | ||
1234 | .type = AVMEDIA_TYPE_VIDEO, | ||
1235 | .config_props = config_props, | ||
1236 | .request_frame= request_frame, | ||
1237 | }, | ||
1238 | { | ||
1239 | .name = "ref", | ||
1240 | .type = AVMEDIA_TYPE_VIDEO, | ||
1241 | .config_props = config_props_ref, | ||
1242 | .request_frame= request_frame_ref, | ||
1243 | }, | ||
1244 | }; | ||
1245 | |||
1246 | const FFFilter ff_vf_scale2ref = { | ||
1247 | .p.name = "scale2ref", | ||
1248 | .p.description = NULL_IF_CONFIG_SMALL("Scale the input video size and/or convert the image format to the given reference."), | ||
1249 | .p.priv_class = &scale2ref_class, | ||
1250 | .preinit = preinit, | ||
1251 | .init = init, | ||
1252 | .uninit = uninit, | ||
1253 | .priv_size = sizeof(ScaleContext), | ||
1254 | FILTER_INPUTS(avfilter_vf_scale2ref_inputs), | ||
1255 | FILTER_OUTPUTS(avfilter_vf_scale2ref_outputs), | ||
1256 | FILTER_QUERY_FUNC2(query_formats), | ||
1257 | .process_command = process_command, | ||
1258 | }; | ||
1259 |