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