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 "formats.h" | ||
32 | #include "internal.h" | ||
33 | #include "scale_eval.h" | ||
34 | #include "video.h" | ||
35 | #include "libavutil/avstring.h" | ||
36 | #include "libavutil/eval.h" | ||
37 | #include "libavutil/internal.h" | ||
38 | #include "libavutil/mathematics.h" | ||
39 | #include "libavutil/opt.h" | ||
40 | #include "libavutil/parseutils.h" | ||
41 | #include "libavutil/pixdesc.h" | ||
42 | #include "libavutil/imgutils.h" | ||
43 | #include "libswscale/swscale.h" | ||
44 | |||
45 | static const char *const var_names[] = { | ||
46 | "in_w", "iw", | ||
47 | "in_h", "ih", | ||
48 | "out_w", "ow", | ||
49 | "out_h", "oh", | ||
50 | "a", | ||
51 | "sar", | ||
52 | "dar", | ||
53 | "hsub", | ||
54 | "vsub", | ||
55 | "ohsub", | ||
56 | "ovsub", | ||
57 | "n", | ||
58 | "t", | ||
59 | #if FF_API_FRAME_PKT | ||
60 | "pos", | ||
61 | #endif | ||
62 | "main_w", | ||
63 | "main_h", | ||
64 | "main_a", | ||
65 | "main_sar", | ||
66 | "main_dar", "mdar", | ||
67 | "main_hsub", | ||
68 | "main_vsub", | ||
69 | "main_n", | ||
70 | "main_t", | ||
71 | "main_pos", | ||
72 | NULL | ||
73 | }; | ||
74 | |||
75 | enum var_name { | ||
76 | VAR_IN_W, VAR_IW, | ||
77 | VAR_IN_H, VAR_IH, | ||
78 | VAR_OUT_W, VAR_OW, | ||
79 | VAR_OUT_H, VAR_OH, | ||
80 | VAR_A, | ||
81 | VAR_SAR, | ||
82 | VAR_DAR, | ||
83 | VAR_HSUB, | ||
84 | VAR_VSUB, | ||
85 | VAR_OHSUB, | ||
86 | VAR_OVSUB, | ||
87 | VAR_N, | ||
88 | VAR_T, | ||
89 | #if FF_API_FRAME_PKT | ||
90 | VAR_POS, | ||
91 | #endif | ||
92 | VAR_S2R_MAIN_W, | ||
93 | VAR_S2R_MAIN_H, | ||
94 | VAR_S2R_MAIN_A, | ||
95 | VAR_S2R_MAIN_SAR, | ||
96 | VAR_S2R_MAIN_DAR, VAR_S2R_MDAR, | ||
97 | VAR_S2R_MAIN_HSUB, | ||
98 | VAR_S2R_MAIN_VSUB, | ||
99 | VAR_S2R_MAIN_N, | ||
100 | VAR_S2R_MAIN_T, | ||
101 | VAR_S2R_MAIN_POS, | ||
102 | VARS_NB | ||
103 | }; | ||
104 | |||
105 | enum EvalMode { | ||
106 | EVAL_MODE_INIT, | ||
107 | EVAL_MODE_FRAME, | ||
108 | EVAL_MODE_NB | ||
109 | }; | ||
110 | |||
111 | typedef struct ScaleContext { | ||
112 | const AVClass *class; | ||
113 | struct SwsContext *sws; ///< software scaler context | ||
114 | struct SwsContext *isws[2]; ///< software scaler context for interlaced material | ||
115 | // context used for forwarding options to sws | ||
116 | struct SwsContext *sws_opts; | ||
117 | |||
118 | /** | ||
119 | * New dimensions. Special values are: | ||
120 | * 0 = original width/height | ||
121 | * -1 = keep original aspect | ||
122 | * -N = try to keep aspect but make sure it is divisible by N | ||
123 | */ | ||
124 | int w, h; | ||
125 | char *size_str; | ||
126 | double param[2]; // sws params | ||
127 | |||
128 | int hsub, vsub; ///< chroma subsampling | ||
129 | int slice_y; ///< top of current output slice | ||
130 | int input_is_pal; ///< set to 1 if the input format is paletted | ||
131 | int output_is_pal; ///< set to 1 if the output format is paletted | ||
132 | int interlaced; | ||
133 | |||
134 | char *w_expr; ///< width expression string | ||
135 | char *h_expr; ///< height expression string | ||
136 | AVExpr *w_pexpr; | ||
137 | AVExpr *h_pexpr; | ||
138 | double var_values[VARS_NB]; | ||
139 | |||
140 | char *flags_str; | ||
141 | |||
142 | int in_color_matrix; | ||
143 | int out_color_matrix; | ||
144 | |||
145 | int in_range; | ||
146 | int in_frame_range; | ||
147 | int out_range; | ||
148 | |||
149 | int out_h_chr_pos; | ||
150 | int out_v_chr_pos; | ||
151 | int in_h_chr_pos; | ||
152 | int in_v_chr_pos; | ||
153 | |||
154 | int force_original_aspect_ratio; | ||
155 | int force_divisible_by; | ||
156 | |||
157 | int eval_mode; ///< expression evaluation mode | ||
158 | |||
159 | } ScaleContext; | ||
160 | |||
161 | const AVFilter ff_vf_scale2ref; | ||
162 | |||
163 | static int config_props(AVFilterLink *outlink); | ||
164 | |||
165 | 19378 | static int check_exprs(AVFilterContext *ctx) | |
166 | { | ||
167 | 19378 | ScaleContext *scale = ctx->priv; | |
168 | 19378 | unsigned vars_w[VARS_NB] = { 0 }, vars_h[VARS_NB] = { 0 }; | |
169 | |||
170 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 19378 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
19378 | if (!scale->w_pexpr && !scale->h_pexpr) |
171 | ✗ | return AVERROR(EINVAL); | |
172 | |||
173 |
1/2✓ Branch 0 taken 19378 times.
✗ Branch 1 not taken.
|
19378 | if (scale->w_pexpr) |
174 | 19378 | av_expr_count_vars(scale->w_pexpr, vars_w, VARS_NB); | |
175 |
2/2✓ Branch 0 taken 12646 times.
✓ Branch 1 taken 6732 times.
|
19378 | if (scale->h_pexpr) |
176 | 12646 | av_expr_count_vars(scale->h_pexpr, vars_h, VARS_NB); | |
177 | |||
178 |
2/4✓ Branch 0 taken 19378 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19378 times.
|
19378 | if (vars_w[VAR_OUT_W] || vars_w[VAR_OW]) { |
179 | ✗ | av_log(ctx, AV_LOG_ERROR, "Width expression cannot be self-referencing: '%s'.\n", scale->w_expr); | |
180 | ✗ | return AVERROR(EINVAL); | |
181 | } | ||
182 | |||
183 |
2/4✓ Branch 0 taken 19378 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19378 times.
|
19378 | if (vars_h[VAR_OUT_H] || vars_h[VAR_OH]) { |
184 | ✗ | av_log(ctx, AV_LOG_ERROR, "Height expression cannot be self-referencing: '%s'.\n", scale->h_expr); | |
185 | ✗ | return AVERROR(EINVAL); | |
186 | } | ||
187 | |||
188 |
2/4✓ Branch 0 taken 19378 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19378 times.
|
19378 | if ((vars_w[VAR_OUT_H] || vars_w[VAR_OH]) && |
189 | ✗ | (vars_h[VAR_OUT_W] || vars_h[VAR_OW])) { | |
190 | ✗ | av_log(ctx, AV_LOG_WARNING, "Circular references detected for width '%s' and height '%s' - possibly invalid.\n", scale->w_expr, scale->h_expr); | |
191 | } | ||
192 | |||
193 |
2/2✓ Branch 0 taken 19374 times.
✓ Branch 1 taken 4 times.
|
19378 | if (ctx->filter != &ff_vf_scale2ref && |
194 |
2/4✓ Branch 0 taken 19374 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19374 times.
✗ Branch 3 not taken.
|
19374 | (vars_w[VAR_S2R_MAIN_W] || vars_h[VAR_S2R_MAIN_W] || |
195 |
2/4✓ Branch 0 taken 19374 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19374 times.
✗ Branch 3 not taken.
|
19374 | vars_w[VAR_S2R_MAIN_H] || vars_h[VAR_S2R_MAIN_H] || |
196 |
2/4✓ Branch 0 taken 19374 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19374 times.
✗ Branch 3 not taken.
|
19374 | vars_w[VAR_S2R_MAIN_A] || vars_h[VAR_S2R_MAIN_A] || |
197 |
2/4✓ Branch 0 taken 19374 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19374 times.
✗ Branch 3 not taken.
|
19374 | vars_w[VAR_S2R_MAIN_SAR] || vars_h[VAR_S2R_MAIN_SAR] || |
198 |
2/4✓ Branch 0 taken 19374 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19374 times.
✗ Branch 3 not taken.
|
19374 | vars_w[VAR_S2R_MAIN_DAR] || vars_h[VAR_S2R_MAIN_DAR] || |
199 |
2/4✓ Branch 0 taken 19374 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19374 times.
✗ Branch 3 not taken.
|
19374 | vars_w[VAR_S2R_MDAR] || vars_h[VAR_S2R_MDAR] || |
200 |
2/4✓ Branch 0 taken 19374 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19374 times.
✗ Branch 3 not taken.
|
19374 | vars_w[VAR_S2R_MAIN_HSUB] || vars_h[VAR_S2R_MAIN_HSUB] || |
201 |
2/4✓ Branch 0 taken 19374 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19374 times.
✗ Branch 3 not taken.
|
19374 | vars_w[VAR_S2R_MAIN_VSUB] || vars_h[VAR_S2R_MAIN_VSUB] || |
202 |
2/4✓ Branch 0 taken 19374 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19374 times.
✗ Branch 3 not taken.
|
19374 | vars_w[VAR_S2R_MAIN_N] || vars_h[VAR_S2R_MAIN_N] || |
203 |
2/4✓ Branch 0 taken 19374 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19374 times.
✗ Branch 3 not taken.
|
19374 | vars_w[VAR_S2R_MAIN_T] || vars_h[VAR_S2R_MAIN_T] || |
204 |
2/4✓ Branch 0 taken 19374 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19374 times.
|
19374 | vars_w[VAR_S2R_MAIN_POS] || vars_h[VAR_S2R_MAIN_POS]) ) { |
205 | ✗ | av_log(ctx, AV_LOG_ERROR, "Expressions with scale2ref variables are not valid in scale filter.\n"); | |
206 | ✗ | return AVERROR(EINVAL); | |
207 | } | ||
208 | |||
209 |
1/2✓ Branch 0 taken 19378 times.
✗ Branch 1 not taken.
|
19378 | if (scale->eval_mode == EVAL_MODE_INIT && |
210 |
2/4✓ Branch 0 taken 19378 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19378 times.
✗ Branch 3 not taken.
|
19378 | (vars_w[VAR_N] || vars_h[VAR_N] || |
211 |
2/4✓ Branch 0 taken 19378 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19378 times.
✗ Branch 3 not taken.
|
19378 | vars_w[VAR_T] || vars_h[VAR_T] || |
212 | #if FF_API_FRAME_PKT | ||
213 |
2/4✓ Branch 0 taken 19378 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19378 times.
✗ Branch 3 not taken.
|
19378 | vars_w[VAR_POS] || vars_h[VAR_POS] || |
214 | #endif | ||
215 |
2/4✓ Branch 0 taken 19378 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19378 times.
✗ Branch 3 not taken.
|
19378 | vars_w[VAR_S2R_MAIN_N] || vars_h[VAR_S2R_MAIN_N] || |
216 |
2/4✓ Branch 0 taken 19378 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19378 times.
✗ Branch 3 not taken.
|
19378 | vars_w[VAR_S2R_MAIN_T] || vars_h[VAR_S2R_MAIN_T] || |
217 |
2/4✓ Branch 0 taken 19378 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19378 times.
|
19378 | vars_w[VAR_S2R_MAIN_POS] || vars_h[VAR_S2R_MAIN_POS]) ) { |
218 | ✗ | av_log(ctx, AV_LOG_ERROR, "Expressions with frame variables 'n', 't', 'pos' are not valid in init eval_mode.\n"); | |
219 | ✗ | return AVERROR(EINVAL); | |
220 | } | ||
221 | |||
222 | 19378 | return 0; | |
223 | } | ||
224 | |||
225 | 19378 | static int scale_parse_expr(AVFilterContext *ctx, char *str_expr, AVExpr **pexpr_ptr, const char *var, const char *args) | |
226 | { | ||
227 | 19378 | ScaleContext *scale = ctx->priv; | |
228 | 19378 | int ret, is_inited = 0; | |
229 | 19378 | char *old_str_expr = NULL; | |
230 | 19378 | AVExpr *old_pexpr = NULL; | |
231 | |||
232 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19378 times.
|
19378 | if (str_expr) { |
233 | ✗ | old_str_expr = av_strdup(str_expr); | |
234 | ✗ | if (!old_str_expr) | |
235 | ✗ | return AVERROR(ENOMEM); | |
236 | ✗ | av_opt_set(scale, var, args, 0); | |
237 | } | ||
238 | |||
239 |
2/2✓ Branch 0 taken 5914 times.
✓ Branch 1 taken 13464 times.
|
19378 | if (*pexpr_ptr) { |
240 | 5914 | old_pexpr = *pexpr_ptr; | |
241 | 5914 | *pexpr_ptr = NULL; | |
242 | 5914 | is_inited = 1; | |
243 | } | ||
244 | |||
245 | 19378 | ret = av_expr_parse(pexpr_ptr, args, var_names, | |
246 | NULL, NULL, NULL, NULL, 0, ctx); | ||
247 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19378 times.
|
19378 | if (ret < 0) { |
248 | ✗ | av_log(ctx, AV_LOG_ERROR, "Cannot parse expression for %s: '%s'\n", var, args); | |
249 | ✗ | goto revert; | |
250 | } | ||
251 | |||
252 | 19378 | ret = check_exprs(ctx); | |
253 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19378 times.
|
19378 | if (ret < 0) |
254 | ✗ | goto revert; | |
255 | |||
256 |
3/4✓ Branch 0 taken 5914 times.
✓ Branch 1 taken 13464 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5914 times.
|
19378 | if (is_inited && (ret = config_props(ctx->outputs[0])) < 0) |
257 | ✗ | goto revert; | |
258 | |||
259 | 19378 | av_expr_free(old_pexpr); | |
260 | 19378 | old_pexpr = NULL; | |
261 | 19378 | av_freep(&old_str_expr); | |
262 | |||
263 | 19378 | return 0; | |
264 | |||
265 | ✗ | revert: | |
266 | ✗ | av_expr_free(*pexpr_ptr); | |
267 | ✗ | *pexpr_ptr = NULL; | |
268 | ✗ | if (old_str_expr) { | |
269 | ✗ | av_opt_set(scale, var, old_str_expr, 0); | |
270 | ✗ | av_free(old_str_expr); | |
271 | } | ||
272 | ✗ | if (old_pexpr) | |
273 | ✗ | *pexpr_ptr = old_pexpr; | |
274 | |||
275 | ✗ | return ret; | |
276 | } | ||
277 | |||
278 | 6732 | static av_cold int preinit(AVFilterContext *ctx) | |
279 | { | ||
280 | 6732 | ScaleContext *scale = ctx->priv; | |
281 | int ret; | ||
282 | |||
283 | 6732 | scale->sws_opts = sws_alloc_context(); | |
284 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6732 times.
|
6732 | if (!scale->sws_opts) |
285 | ✗ | return AVERROR(ENOMEM); | |
286 | |||
287 | // set threads=0, so we can later check whether the user modified it | ||
288 | 6732 | ret = av_opt_set_int(scale->sws_opts, "threads", 0, 0); | |
289 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6732 times.
|
6732 | if (ret < 0) |
290 | ✗ | return ret; | |
291 | |||
292 | 6732 | return 0; | |
293 | } | ||
294 | |||
295 | 6732 | static av_cold int init(AVFilterContext *ctx) | |
296 | { | ||
297 | 6732 | ScaleContext *scale = ctx->priv; | |
298 | int64_t threads; | ||
299 | int ret; | ||
300 | |||
301 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 6732 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
6732 | if (scale->size_str && (scale->w_expr || scale->h_expr)) { |
302 | ✗ | av_log(ctx, AV_LOG_ERROR, | |
303 | "Size and width/height expressions cannot be set at the same time.\n"); | ||
304 | ✗ | return AVERROR(EINVAL); | |
305 | } | ||
306 | |||
307 |
3/4✓ Branch 0 taken 704 times.
✓ Branch 1 taken 6028 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 704 times.
|
6732 | if (scale->w_expr && !scale->h_expr) |
308 | ✗ | FFSWAP(char *, scale->w_expr, scale->size_str); | |
309 | |||
310 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6732 times.
|
6732 | if (scale->size_str) { |
311 | char buf[32]; | ||
312 | ✗ | if ((ret = av_parse_video_size(&scale->w, &scale->h, scale->size_str)) < 0) { | |
313 | ✗ | av_log(ctx, AV_LOG_ERROR, | |
314 | "Invalid size '%s'\n", scale->size_str); | ||
315 | ✗ | return ret; | |
316 | } | ||
317 | ✗ | snprintf(buf, sizeof(buf)-1, "%d", scale->w); | |
318 | ✗ | av_opt_set(scale, "w", buf, 0); | |
319 | ✗ | snprintf(buf, sizeof(buf)-1, "%d", scale->h); | |
320 | ✗ | av_opt_set(scale, "h", buf, 0); | |
321 | } | ||
322 |
2/2✓ Branch 0 taken 6028 times.
✓ Branch 1 taken 704 times.
|
6732 | if (!scale->w_expr) |
323 | 6028 | av_opt_set(scale, "w", "iw", 0); | |
324 |
2/2✓ Branch 0 taken 6028 times.
✓ Branch 1 taken 704 times.
|
6732 | if (!scale->h_expr) |
325 | 6028 | av_opt_set(scale, "h", "ih", 0); | |
326 | |||
327 | 6732 | ret = scale_parse_expr(ctx, NULL, &scale->w_pexpr, "width", scale->w_expr); | |
328 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6732 times.
|
6732 | if (ret < 0) |
329 | ✗ | return ret; | |
330 | |||
331 | 6732 | ret = scale_parse_expr(ctx, NULL, &scale->h_pexpr, "height", scale->h_expr); | |
332 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6732 times.
|
6732 | if (ret < 0) |
333 | ✗ | return ret; | |
334 | |||
335 | 6732 | av_log(ctx, AV_LOG_VERBOSE, "w:%s h:%s flags:'%s' interl:%d\n", | |
336 | 6732 | scale->w_expr, scale->h_expr, (char *)av_x_if_null(scale->flags_str, ""), scale->interlaced); | |
337 | |||
338 |
3/4✓ Branch 0 taken 6732 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
✓ Branch 3 taken 6674 times.
|
6732 | if (scale->flags_str && *scale->flags_str) { |
339 | 58 | ret = av_opt_set(scale->sws_opts, "sws_flags", scale->flags_str, 0); | |
340 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
|
58 | if (ret < 0) |
341 | ✗ | return ret; | |
342 | } | ||
343 | |||
344 |
2/2✓ Branch 0 taken 13464 times.
✓ Branch 1 taken 6732 times.
|
20196 | for (int i = 0; i < FF_ARRAY_ELEMS(scale->param); i++) |
345 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13464 times.
|
13464 | if (scale->param[i] != DBL_MAX) { |
346 | ✗ | ret = av_opt_set_double(scale->sws_opts, i ? "param1" : "param0", | |
347 | scale->param[i], 0); | ||
348 | ✗ | if (ret < 0) | |
349 | ✗ | return ret; | |
350 | } | ||
351 | |||
352 | // use generic thread-count if the user did not set it explicitly | ||
353 | 6732 | ret = av_opt_get_int(scale->sws_opts, "threads", 0, &threads); | |
354 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6732 times.
|
6732 | if (ret < 0) |
355 | ✗ | return ret; | |
356 |
1/2✓ Branch 0 taken 6732 times.
✗ Branch 1 not taken.
|
6732 | if (!threads) |
357 | 6732 | av_opt_set_int(scale->sws_opts, "threads", ff_filter_get_nb_threads(ctx), 0); | |
358 | |||
359 | 6732 | scale->in_frame_range = AVCOL_RANGE_UNSPECIFIED; | |
360 | |||
361 | 6732 | return 0; | |
362 | } | ||
363 | |||
364 | 6732 | static av_cold void uninit(AVFilterContext *ctx) | |
365 | { | ||
366 | 6732 | ScaleContext *scale = ctx->priv; | |
367 | 6732 | av_expr_free(scale->w_pexpr); | |
368 | 6732 | av_expr_free(scale->h_pexpr); | |
369 | 6732 | scale->w_pexpr = scale->h_pexpr = NULL; | |
370 | 6732 | sws_freeContext(scale->sws_opts); | |
371 | 6732 | sws_freeContext(scale->sws); | |
372 | 6732 | sws_freeContext(scale->isws[0]); | |
373 | 6732 | sws_freeContext(scale->isws[1]); | |
374 | 6732 | scale->sws = NULL; | |
375 | 6732 | } | |
376 | |||
377 | 3834 | static int query_formats(AVFilterContext *ctx) | |
378 | { | ||
379 | AVFilterFormats *formats; | ||
380 | const AVPixFmtDescriptor *desc; | ||
381 | enum AVPixelFormat pix_fmt; | ||
382 | int ret; | ||
383 | |||
384 | 3834 | desc = NULL; | |
385 | 3834 | formats = NULL; | |
386 |
2/2✓ Branch 1 taken 874152 times.
✓ Branch 2 taken 3834 times.
|
877986 | while ((desc = av_pix_fmt_desc_next(desc))) { |
387 | 874152 | pix_fmt = av_pix_fmt_desc_get_id(desc); | |
388 |
3/4✓ Branch 1 taken 115020 times.
✓ Branch 2 taken 759132 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 115020 times.
|
989172 | if ((sws_isSupportedInput(pix_fmt) || |
389 | 115020 | sws_isSupportedEndiannessConversion(pix_fmt)) | |
390 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 759132 times.
|
759132 | && (ret = ff_add_format(&formats, pix_fmt)) < 0) { |
391 | ✗ | return ret; | |
392 | } | ||
393 | } | ||
394 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3834 times.
|
3834 | if ((ret = ff_formats_ref(formats, &ctx->inputs[0]->outcfg.formats)) < 0) |
395 | ✗ | return ret; | |
396 | |||
397 | 3834 | desc = NULL; | |
398 | 3834 | formats = NULL; | |
399 |
2/2✓ Branch 1 taken 874152 times.
✓ Branch 2 taken 3834 times.
|
877986 | while ((desc = av_pix_fmt_desc_next(desc))) { |
400 | 874152 | pix_fmt = av_pix_fmt_desc_get_id(desc); | |
401 |
5/6✓ Branch 1 taken 164862 times.
✓ Branch 2 taken 709290 times.
✓ Branch 3 taken 161028 times.
✓ Branch 4 taken 3834 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 161028 times.
|
1035180 | if ((sws_isSupportedOutput(pix_fmt) || pix_fmt == AV_PIX_FMT_PAL8 || |
402 | 161028 | sws_isSupportedEndiannessConversion(pix_fmt)) | |
403 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 713124 times.
|
713124 | && (ret = ff_add_format(&formats, pix_fmt)) < 0) { |
404 | ✗ | return ret; | |
405 | } | ||
406 | } | ||
407 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3834 times.
|
3834 | if ((ret = ff_formats_ref(formats, &ctx->outputs[0]->incfg.formats)) < 0) |
408 | ✗ | return ret; | |
409 | |||
410 | 3834 | return 0; | |
411 | } | ||
412 | |||
413 | 12660 | static int scale_eval_dimensions(AVFilterContext *ctx) | |
414 | { | ||
415 | 12660 | ScaleContext *scale = ctx->priv; | |
416 | 12660 | const char scale2ref = ctx->filter == &ff_vf_scale2ref; | |
417 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12659 times.
|
12660 | const AVFilterLink *inlink = scale2ref ? ctx->inputs[1] : ctx->inputs[0]; |
418 | 12660 | const AVFilterLink *outlink = ctx->outputs[0]; | |
419 | 12660 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); | |
420 | 12660 | const AVPixFmtDescriptor *out_desc = av_pix_fmt_desc_get(outlink->format); | |
421 | char *expr; | ||
422 | int eval_w, eval_h; | ||
423 | int ret; | ||
424 | double res; | ||
425 | const AVPixFmtDescriptor *main_desc; | ||
426 | const AVFilterLink *main_link; | ||
427 | |||
428 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12659 times.
|
12660 | if (scale2ref) { |
429 | 1 | main_link = ctx->inputs[0]; | |
430 | 1 | main_desc = av_pix_fmt_desc_get(main_link->format); | |
431 | } | ||
432 | |||
433 | 12660 | scale->var_values[VAR_IN_W] = scale->var_values[VAR_IW] = inlink->w; | |
434 | 12660 | scale->var_values[VAR_IN_H] = scale->var_values[VAR_IH] = inlink->h; | |
435 | 12660 | scale->var_values[VAR_OUT_W] = scale->var_values[VAR_OW] = NAN; | |
436 | 12660 | scale->var_values[VAR_OUT_H] = scale->var_values[VAR_OH] = NAN; | |
437 | 12660 | scale->var_values[VAR_A] = (double) inlink->w / inlink->h; | |
438 | 25320 | scale->var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? | |
439 |
2/2✓ Branch 0 taken 596 times.
✓ Branch 1 taken 12064 times.
|
12660 | (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1; |
440 | 12660 | scale->var_values[VAR_DAR] = scale->var_values[VAR_A] * scale->var_values[VAR_SAR]; | |
441 | 12660 | scale->var_values[VAR_HSUB] = 1 << desc->log2_chroma_w; | |
442 | 12660 | scale->var_values[VAR_VSUB] = 1 << desc->log2_chroma_h; | |
443 | 12660 | scale->var_values[VAR_OHSUB] = 1 << out_desc->log2_chroma_w; | |
444 | 12660 | scale->var_values[VAR_OVSUB] = 1 << out_desc->log2_chroma_h; | |
445 | |||
446 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12659 times.
|
12660 | if (scale2ref) { |
447 | 1 | scale->var_values[VAR_S2R_MAIN_W] = main_link->w; | |
448 | 1 | scale->var_values[VAR_S2R_MAIN_H] = main_link->h; | |
449 | 1 | scale->var_values[VAR_S2R_MAIN_A] = (double) main_link->w / main_link->h; | |
450 | 2 | scale->var_values[VAR_S2R_MAIN_SAR] = main_link->sample_aspect_ratio.num ? | |
451 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | (double) main_link->sample_aspect_ratio.num / main_link->sample_aspect_ratio.den : 1; |
452 | 1 | scale->var_values[VAR_S2R_MAIN_DAR] = scale->var_values[VAR_S2R_MDAR] = | |
453 | 1 | scale->var_values[VAR_S2R_MAIN_A] * scale->var_values[VAR_S2R_MAIN_SAR]; | |
454 | 1 | scale->var_values[VAR_S2R_MAIN_HSUB] = 1 << main_desc->log2_chroma_w; | |
455 | 1 | scale->var_values[VAR_S2R_MAIN_VSUB] = 1 << main_desc->log2_chroma_h; | |
456 | } | ||
457 | |||
458 | 12660 | res = av_expr_eval(scale->w_pexpr, scale->var_values, NULL); | |
459 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12660 times.
|
12660 | eval_w = scale->var_values[VAR_OUT_W] = scale->var_values[VAR_OW] = (int) res == 0 ? inlink->w : (int) res; |
460 | |||
461 | 12660 | res = av_expr_eval(scale->h_pexpr, scale->var_values, NULL); | |
462 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12660 times.
|
12660 | if (isnan(res)) { |
463 | ✗ | expr = scale->h_expr; | |
464 | ✗ | ret = AVERROR(EINVAL); | |
465 | ✗ | goto fail; | |
466 | } | ||
467 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12660 times.
|
12660 | eval_h = scale->var_values[VAR_OUT_H] = scale->var_values[VAR_OH] = (int) res == 0 ? inlink->h : (int) res; |
468 | |||
469 | 12660 | res = av_expr_eval(scale->w_pexpr, scale->var_values, NULL); | |
470 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12660 times.
|
12660 | if (isnan(res)) { |
471 | ✗ | expr = scale->w_expr; | |
472 | ✗ | ret = AVERROR(EINVAL); | |
473 | ✗ | goto fail; | |
474 | } | ||
475 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12660 times.
|
12660 | eval_w = scale->var_values[VAR_OUT_W] = scale->var_values[VAR_OW] = (int) res == 0 ? inlink->w : (int) res; |
476 | |||
477 | 12660 | scale->w = eval_w; | |
478 | 12660 | scale->h = eval_h; | |
479 | |||
480 | 12660 | return 0; | |
481 | |||
482 | ✗ | fail: | |
483 | ✗ | av_log(ctx, AV_LOG_ERROR, | |
484 | "Error when evaluating the expression '%s'.\n", expr); | ||
485 | ✗ | return ret; | |
486 | } | ||
487 | |||
488 | 12660 | static int config_props(AVFilterLink *outlink) | |
489 | { | ||
490 | 12660 | AVFilterContext *ctx = outlink->src; | |
491 | 12660 | AVFilterLink *inlink0 = outlink->src->inputs[0]; | |
492 | 25320 | AVFilterLink *inlink = ctx->filter == &ff_vf_scale2ref ? | |
493 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12659 times.
|
12660 | outlink->src->inputs[1] : |
494 | 12659 | outlink->src->inputs[0]; | |
495 | 12660 | enum AVPixelFormat outfmt = outlink->format; | |
496 | 12660 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); | |
497 | 12660 | const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(outfmt); | |
498 | 12660 | ScaleContext *scale = ctx->priv; | |
499 | 12660 | uint8_t *flags_val = NULL; | |
500 | int ret; | ||
501 | |||
502 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12660 times.
|
12660 | if ((ret = scale_eval_dimensions(ctx)) < 0) |
503 | ✗ | goto fail; | |
504 | |||
505 | 12660 | outlink->w = scale->w; | |
506 | 12660 | outlink->h = scale->h; | |
507 | |||
508 | 12660 | ff_scale_adjust_dimensions(inlink, &outlink->w, &outlink->h, | |
509 | scale->force_original_aspect_ratio, | ||
510 | scale->force_divisible_by); | ||
511 | |||
512 | if (outlink->w > INT_MAX || | ||
513 | outlink->h > INT_MAX || | ||
514 | (outlink->h * inlink->w) > INT_MAX || | ||
515 | (outlink->w * inlink->h) > INT_MAX) | ||
516 | av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n"); | ||
517 | |||
518 | /* TODO: make algorithm configurable */ | ||
519 | |||
520 | 12660 | scale->input_is_pal = desc->flags & AV_PIX_FMT_FLAG_PAL; | |
521 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 12619 times.
|
12660 | if (outfmt == AV_PIX_FMT_PAL8) outfmt = AV_PIX_FMT_BGR8; |
522 | 12660 | scale->output_is_pal = av_pix_fmt_desc_get(outfmt)->flags & AV_PIX_FMT_FLAG_PAL; | |
523 | |||
524 |
2/2✓ Branch 0 taken 8577 times.
✓ Branch 1 taken 4083 times.
|
12660 | if (scale->sws) |
525 | 8577 | sws_freeContext(scale->sws); | |
526 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12660 times.
|
12660 | if (scale->isws[0]) |
527 | ✗ | sws_freeContext(scale->isws[0]); | |
528 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12660 times.
|
12660 | if (scale->isws[1]) |
529 | ✗ | sws_freeContext(scale->isws[1]); | |
530 | 12660 | scale->isws[0] = scale->isws[1] = scale->sws = NULL; | |
531 |
2/2✓ Branch 0 taken 11471 times.
✓ Branch 1 taken 1189 times.
|
12660 | if (inlink0->w == outlink->w && |
532 |
2/2✓ Branch 0 taken 11431 times.
✓ Branch 1 taken 40 times.
|
11471 | inlink0->h == outlink->h && |
533 |
2/2✓ Branch 0 taken 11429 times.
✓ Branch 1 taken 2 times.
|
11431 | scale->out_color_matrix == AVCOL_SPC_UNSPECIFIED && |
534 |
1/2✓ Branch 0 taken 11429 times.
✗ Branch 1 not taken.
|
11429 | scale->in_range == scale->out_range && |
535 |
2/2✓ Branch 0 taken 446 times.
✓ Branch 1 taken 10983 times.
|
11429 | inlink0->format == outlink->format) |
536 | ; | ||
537 | else { | ||
538 | 12214 | struct SwsContext **swscs[3] = {&scale->sws, &scale->isws[0], &scale->isws[1]}; | |
539 | int i; | ||
540 | |||
541 |
1/2✓ Branch 0 taken 12214 times.
✗ Branch 1 not taken.
|
12214 | for (i = 0; i < 3; i++) { |
542 | 12214 | int in_v_chr_pos = scale->in_v_chr_pos, out_v_chr_pos = scale->out_v_chr_pos; | |
543 | 12214 | struct SwsContext *const s = sws_alloc_context(); | |
544 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12214 times.
|
12214 | if (!s) |
545 | ✗ | return AVERROR(ENOMEM); | |
546 | 12214 | *swscs[i] = s; | |
547 | |||
548 | 12214 | ret = av_opt_copy(s, scale->sws_opts); | |
549 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12214 times.
|
12214 | if (ret < 0) |
550 | ✗ | return ret; | |
551 | |||
552 | 12214 | av_opt_set_int(s, "srcw", inlink0 ->w, 0); | |
553 | 12214 | av_opt_set_int(s, "srch", inlink0 ->h >> !!i, 0); | |
554 | 12214 | av_opt_set_int(s, "src_format", inlink0->format, 0); | |
555 | 12214 | av_opt_set_int(s, "dstw", outlink->w, 0); | |
556 | 12214 | av_opt_set_int(s, "dsth", outlink->h >> !!i, 0); | |
557 | 12214 | av_opt_set_int(s, "dst_format", outfmt, 0); | |
558 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12212 times.
|
12214 | if (scale->in_range != AVCOL_RANGE_UNSPECIFIED) |
559 | 2 | av_opt_set_int(s, "src_range", | |
560 | 2 | scale->in_range == AVCOL_RANGE_JPEG, 0); | |
561 |
2/2✓ Branch 0 taken 8578 times.
✓ Branch 1 taken 3634 times.
|
12212 | else if (scale->in_frame_range != AVCOL_RANGE_UNSPECIFIED) |
562 | 8578 | av_opt_set_int(s, "src_range", | |
563 | 8578 | scale->in_frame_range == AVCOL_RANGE_JPEG, 0); | |
564 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12212 times.
|
12214 | if (scale->out_range != AVCOL_RANGE_UNSPECIFIED) |
565 | 2 | av_opt_set_int(s, "dst_range", | |
566 | 2 | scale->out_range == AVCOL_RANGE_JPEG, 0); | |
567 | |||
568 | /* Override chroma location default settings to have the correct | ||
569 | * chroma positions. MPEG chroma positions are used by convention. | ||
570 | * Note that this works for both MPEG-1/JPEG and MPEG-2/4 chroma | ||
571 | * locations, since they share a vertical alignment */ | ||
572 |
3/4✓ Branch 0 taken 10596 times.
✓ Branch 1 taken 1618 times.
✓ Branch 2 taken 10596 times.
✗ Branch 3 not taken.
|
12214 | if (desc->log2_chroma_h == 1 && scale->in_v_chr_pos == -513) { |
573 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 10596 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
10596 | in_v_chr_pos = (i == 0) ? 128 : (i == 1) ? 64 : 192; |
574 | } | ||
575 | |||
576 |
4/4✓ Branch 0 taken 2756 times.
✓ Branch 1 taken 9458 times.
✓ Branch 2 taken 2755 times.
✓ Branch 3 taken 1 times.
|
12214 | if (outdesc->log2_chroma_h == 1 && scale->out_v_chr_pos == -513) { |
577 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2755 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
2755 | out_v_chr_pos = (i == 0) ? 128 : (i == 1) ? 64 : 192; |
578 | } | ||
579 | |||
580 | 12214 | av_opt_set_int(s, "src_h_chr_pos", scale->in_h_chr_pos, 0); | |
581 | 12214 | av_opt_set_int(s, "src_v_chr_pos", in_v_chr_pos, 0); | |
582 | 12214 | av_opt_set_int(s, "dst_h_chr_pos", scale->out_h_chr_pos, 0); | |
583 | 12214 | av_opt_set_int(s, "dst_v_chr_pos", out_v_chr_pos, 0); | |
584 | |||
585 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12214 times.
|
12214 | if ((ret = sws_init_context(s, NULL, NULL)) < 0) |
586 | ✗ | return ret; | |
587 |
1/2✓ Branch 0 taken 12214 times.
✗ Branch 1 not taken.
|
12214 | if (!scale->interlaced) |
588 | 12214 | break; | |
589 | } | ||
590 | } | ||
591 | |||
592 |
2/2✓ Branch 0 taken 596 times.
✓ Branch 1 taken 12064 times.
|
12660 | if (inlink0->sample_aspect_ratio.num){ |
593 | 596 | outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h * inlink0->w, outlink->w * inlink0->h}, inlink0->sample_aspect_ratio); | |
594 | } else | ||
595 | 12064 | outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio; | |
596 | |||
597 |
2/2✓ Branch 0 taken 12214 times.
✓ Branch 1 taken 446 times.
|
12660 | if (scale->sws) |
598 | 12214 | av_opt_get(scale->sws, "sws_flags", 0, &flags_val); | |
599 | |||
600 | 12660 | av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d fmt:%s sar:%d/%d -> w:%d h:%d fmt:%s sar:%d/%d flags:%s\n", | |
601 | 12660 | inlink ->w, inlink ->h, av_get_pix_fmt_name( inlink->format), | |
602 | inlink->sample_aspect_ratio.num, inlink->sample_aspect_ratio.den, | ||
603 | 12660 | outlink->w, outlink->h, av_get_pix_fmt_name(outlink->format), | |
604 | outlink->sample_aspect_ratio.num, outlink->sample_aspect_ratio.den, | ||
605 | flags_val); | ||
606 | 12660 | av_freep(&flags_val); | |
607 | |||
608 | 12660 | return 0; | |
609 | |||
610 | ✗ | fail: | |
611 | ✗ | return ret; | |
612 | } | ||
613 | |||
614 | 1 | static int config_props_ref(AVFilterLink *outlink) | |
615 | { | ||
616 | 1 | AVFilterLink *inlink = outlink->src->inputs[1]; | |
617 | |||
618 | 1 | outlink->w = inlink->w; | |
619 | 1 | outlink->h = inlink->h; | |
620 | 1 | outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; | |
621 | 1 | outlink->time_base = inlink->time_base; | |
622 | 1 | outlink->frame_rate = inlink->frame_rate; | |
623 | |||
624 | 1 | return 0; | |
625 | } | ||
626 | |||
627 | 5 | static int request_frame(AVFilterLink *outlink) | |
628 | { | ||
629 | 5 | return ff_request_frame(outlink->src->inputs[0]); | |
630 | } | ||
631 | |||
632 | 5 | static int request_frame_ref(AVFilterLink *outlink) | |
633 | { | ||
634 | 5 | return ff_request_frame(outlink->src->inputs[1]); | |
635 | } | ||
636 | |||
637 | ✗ | static void frame_offset(AVFrame *frame, int dir, int is_pal) | |
638 | { | ||
639 | ✗ | for (int i = 0; i < 4 && frame->data[i]; i++) { | |
640 | ✗ | if (i == 1 && is_pal) | |
641 | ✗ | break; | |
642 | ✗ | frame->data[i] += frame->linesize[i] * dir; | |
643 | } | ||
644 | ✗ | } | |
645 | |||
646 | ✗ | static int scale_field(ScaleContext *scale, AVFrame *dst, AVFrame *src, | |
647 | int field) | ||
648 | { | ||
649 | ✗ | int orig_h_src = src->height; | |
650 | ✗ | int orig_h_dst = dst->height; | |
651 | int ret; | ||
652 | |||
653 | // offset the data pointers for the bottom field | ||
654 | ✗ | if (field) { | |
655 | ✗ | frame_offset(src, 1, scale->input_is_pal); | |
656 | ✗ | frame_offset(dst, 1, scale->output_is_pal); | |
657 | } | ||
658 | |||
659 | // take every second line | ||
660 | ✗ | for (int i = 0; i < 4; i++) { | |
661 | ✗ | src->linesize[i] *= 2; | |
662 | ✗ | dst->linesize[i] *= 2; | |
663 | } | ||
664 | ✗ | src->height /= 2; | |
665 | ✗ | dst->height /= 2; | |
666 | |||
667 | ✗ | ret = sws_scale_frame(scale->isws[field], dst, src); | |
668 | ✗ | if (ret < 0) | |
669 | ✗ | return ret; | |
670 | |||
671 | // undo the changes we made above | ||
672 | ✗ | for (int i = 0; i < 4; i++) { | |
673 | ✗ | src->linesize[i] /= 2; | |
674 | ✗ | dst->linesize[i] /= 2; | |
675 | } | ||
676 | ✗ | src->height = orig_h_src; | |
677 | ✗ | dst->height = orig_h_dst; | |
678 | |||
679 | ✗ | if (field) { | |
680 | ✗ | frame_offset(src, -1, scale->input_is_pal); | |
681 | ✗ | frame_offset(dst, -1, scale->output_is_pal); | |
682 | } | ||
683 | |||
684 | ✗ | return 0; | |
685 | } | ||
686 | |||
687 | 45731 | static int scale_frame(AVFilterLink *link, AVFrame *in, AVFrame **frame_out) | |
688 | { | ||
689 | 45731 | AVFilterContext *ctx = link->dst; | |
690 | 45731 | ScaleContext *scale = ctx->priv; | |
691 | 45731 | AVFilterLink *outlink = ctx->outputs[0]; | |
692 | AVFrame *out; | ||
693 | 45731 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); | |
694 | char buf[32]; | ||
695 | int ret; | ||
696 | int in_range; | ||
697 | int frame_changed; | ||
698 | |||
699 | 45731 | *frame_out = NULL; | |
700 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45731 times.
|
45731 | if (in->colorspace == AVCOL_SPC_YCGCO) |
701 | ✗ | av_log(link->dst, AV_LOG_WARNING, "Detected unsupported YCgCo colorspace.\n"); | |
702 | |||
703 | 137192 | frame_changed = in->width != link->w || | |
704 |
1/2✓ Branch 0 taken 45730 times.
✗ Branch 1 not taken.
|
45730 | in->height != link->h || |
705 |
1/2✓ Branch 0 taken 45730 times.
✗ Branch 1 not taken.
|
45730 | in->format != link->format || |
706 |
3/4✓ Branch 0 taken 45730 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 45730 times.
✗ Branch 3 not taken.
|
137191 | in->sample_aspect_ratio.den != link->sample_aspect_ratio.den || |
707 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45730 times.
|
45730 | in->sample_aspect_ratio.num != link->sample_aspect_ratio.num; |
708 | |||
709 |
2/2✓ Branch 0 taken 13148 times.
✓ Branch 1 taken 32583 times.
|
45731 | if (in->color_range != AVCOL_RANGE_UNSPECIFIED && |
710 |
1/2✓ Branch 0 taken 13148 times.
✗ Branch 1 not taken.
|
13148 | scale->in_range == AVCOL_RANGE_UNSPECIFIED && |
711 |
2/2✓ Branch 0 taken 2956 times.
✓ Branch 1 taken 10192 times.
|
13148 | in->color_range != scale->in_frame_range) { |
712 | 2956 | scale->in_frame_range = in->color_range; | |
713 | 2956 | frame_changed = 1; | |
714 | } | ||
715 | |||
716 |
3/4✓ Branch 0 taken 45731 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2957 times.
✓ Branch 3 taken 42774 times.
|
45731 | if (scale->eval_mode == EVAL_MODE_FRAME || frame_changed) { |
717 | 2957 | unsigned vars_w[VARS_NB] = { 0 }, vars_h[VARS_NB] = { 0 }; | |
718 | |||
719 | 2957 | av_expr_count_vars(scale->w_pexpr, vars_w, VARS_NB); | |
720 | 2957 | av_expr_count_vars(scale->h_pexpr, vars_h, VARS_NB); | |
721 | |||
722 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2957 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
2957 | if (scale->eval_mode == EVAL_MODE_FRAME && |
723 | ✗ | !frame_changed && | |
724 | ✗ | ctx->filter != &ff_vf_scale2ref && | |
725 | ✗ | !(vars_w[VAR_N] || vars_w[VAR_T] | |
726 | #if FF_API_FRAME_PKT | ||
727 | ✗ | || vars_w[VAR_POS] | |
728 | #endif | ||
729 | ✗ | ) && | |
730 | ✗ | !(vars_h[VAR_N] || vars_h[VAR_T] | |
731 | #if FF_API_FRAME_PKT | ||
732 | ✗ | || vars_h[VAR_POS] | |
733 | #endif | ||
734 | ✗ | ) && | |
735 | ✗ | scale->w && scale->h) | |
736 | ✗ | goto scale; | |
737 | |||
738 |
1/2✓ Branch 0 taken 2957 times.
✗ Branch 1 not taken.
|
2957 | if (scale->eval_mode == EVAL_MODE_INIT) { |
739 | 2957 | snprintf(buf, sizeof(buf) - 1, "%d", scale->w); | |
740 | 2957 | av_opt_set(scale, "w", buf, 0); | |
741 | 2957 | snprintf(buf, sizeof(buf) - 1, "%d", scale->h); | |
742 | 2957 | av_opt_set(scale, "h", buf, 0); | |
743 | |||
744 | 2957 | ret = scale_parse_expr(ctx, NULL, &scale->w_pexpr, "width", scale->w_expr); | |
745 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2957 times.
|
2957 | if (ret < 0) |
746 | ✗ | return ret; | |
747 | |||
748 | 2957 | ret = scale_parse_expr(ctx, NULL, &scale->h_pexpr, "height", scale->h_expr); | |
749 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2957 times.
|
2957 | if (ret < 0) |
750 | ✗ | return ret; | |
751 | } | ||
752 | |||
753 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2957 times.
|
2957 | if (ctx->filter == &ff_vf_scale2ref) { |
754 | ✗ | scale->var_values[VAR_S2R_MAIN_N] = link->frame_count_out; | |
755 | ✗ | scale->var_values[VAR_S2R_MAIN_T] = TS2T(in->pts, link->time_base); | |
756 | #if FF_API_FRAME_PKT | ||
757 | FF_DISABLE_DEPRECATION_WARNINGS | ||
758 | ✗ | scale->var_values[VAR_S2R_MAIN_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos; | |
759 | FF_ENABLE_DEPRECATION_WARNINGS | ||
760 | #endif | ||
761 | } else { | ||
762 | 2957 | scale->var_values[VAR_N] = link->frame_count_out; | |
763 |
1/2✓ Branch 0 taken 2957 times.
✗ Branch 1 not taken.
|
2957 | scale->var_values[VAR_T] = TS2T(in->pts, link->time_base); |
764 | #if FF_API_FRAME_PKT | ||
765 | FF_DISABLE_DEPRECATION_WARNINGS | ||
766 |
2/2✓ Branch 0 taken 219 times.
✓ Branch 1 taken 2738 times.
|
2957 | scale->var_values[VAR_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos; |
767 | FF_ENABLE_DEPRECATION_WARNINGS | ||
768 | #endif | ||
769 | } | ||
770 | |||
771 | 2957 | link->dst->inputs[0]->format = in->format; | |
772 | 2957 | link->dst->inputs[0]->w = in->width; | |
773 | 2957 | link->dst->inputs[0]->h = in->height; | |
774 | |||
775 | 2957 | link->dst->inputs[0]->sample_aspect_ratio.den = in->sample_aspect_ratio.den; | |
776 | 2957 | link->dst->inputs[0]->sample_aspect_ratio.num = in->sample_aspect_ratio.num; | |
777 | |||
778 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2957 times.
|
2957 | if ((ret = config_props(outlink)) < 0) |
779 | ✗ | return ret; | |
780 | } | ||
781 | |||
782 | 42774 | scale: | |
783 |
2/2✓ Branch 0 taken 3364 times.
✓ Branch 1 taken 42367 times.
|
45731 | if (!scale->sws) { |
784 | 3364 | *frame_out = in; | |
785 | 3364 | return 0; | |
786 | } | ||
787 | |||
788 | 42367 | scale->hsub = desc->log2_chroma_w; | |
789 | 42367 | scale->vsub = desc->log2_chroma_h; | |
790 | |||
791 | 42367 | out = ff_get_video_buffer(outlink, outlink->w, outlink->h); | |
792 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42367 times.
|
42367 | if (!out) { |
793 | ✗ | av_frame_free(&in); | |
794 | ✗ | return AVERROR(ENOMEM); | |
795 | } | ||
796 | 42367 | *frame_out = out; | |
797 | |||
798 | 42367 | av_frame_copy_props(out, in); | |
799 | 42367 | out->width = outlink->w; | |
800 | 42367 | out->height = outlink->h; | |
801 | |||
802 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42367 times.
|
42367 | if (scale->output_is_pal) |
803 | ✗ | avpriv_set_systematic_pal2((uint32_t*)out->data[1], outlink->format == AV_PIX_FMT_PAL8 ? AV_PIX_FMT_BGR8 : outlink->format); | |
804 | |||
805 | 42367 | in_range = in->color_range; | |
806 | |||
807 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42367 times.
|
42367 | if ( scale->in_color_matrix != AVCOL_SPC_UNSPECIFIED |
808 | ✗ | || scale->out_color_matrix != AVCOL_SPC_UNSPECIFIED | |
809 | ✗ | || scale-> in_range != AVCOL_RANGE_UNSPECIFIED | |
810 | ✗ | || in_range != AVCOL_RANGE_UNSPECIFIED | |
811 | ✗ | || scale->out_range != AVCOL_RANGE_UNSPECIFIED) { | |
812 | int in_full, out_full, brightness, contrast, saturation; | ||
813 | const int *inv_table, *table; | ||
814 | |||
815 | 42367 | sws_getColorspaceDetails(scale->sws, (int **)&inv_table, &in_full, | |
816 | (int **)&table, &out_full, | ||
817 | &brightness, &contrast, &saturation); | ||
818 | |||
819 |
2/2✓ Branch 0 taken 42365 times.
✓ Branch 1 taken 2 times.
|
42367 | if (scale->in_color_matrix == -1 /* auto */) |
820 | 42365 | inv_table = sws_getCoefficients(in->colorspace); | |
821 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | else if (scale->in_color_matrix != AVCOL_SPC_UNSPECIFIED) |
822 | 2 | inv_table = sws_getCoefficients(scale->in_color_matrix); | |
823 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 42365 times.
|
42367 | if (scale->out_color_matrix != AVCOL_SPC_UNSPECIFIED) |
824 | 2 | table = sws_getCoefficients(scale->out_color_matrix); | |
825 |
1/2✓ Branch 0 taken 42365 times.
✗ Branch 1 not taken.
|
42365 | else if (scale->in_color_matrix != AVCOL_SPC_UNSPECIFIED) |
826 | 42365 | table = inv_table; | |
827 | |||
828 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 42365 times.
|
42367 | if (scale-> in_range != AVCOL_RANGE_UNSPECIFIED) |
829 | 2 | in_full = (scale-> in_range == AVCOL_RANGE_JPEG); | |
830 |
2/2✓ Branch 0 taken 11355 times.
✓ Branch 1 taken 31010 times.
|
42365 | else if (in_range != AVCOL_RANGE_UNSPECIFIED) |
831 | 11355 | in_full = (in_range == AVCOL_RANGE_JPEG); | |
832 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 42365 times.
|
42367 | if (scale->out_range != AVCOL_RANGE_UNSPECIFIED) |
833 | 2 | out_full = (scale->out_range == AVCOL_RANGE_JPEG); | |
834 | |||
835 | 42367 | sws_setColorspaceDetails(scale->sws, inv_table, in_full, | |
836 | table, out_full, | ||
837 | brightness, contrast, saturation); | ||
838 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42367 times.
|
42367 | if (scale->isws[0]) |
839 | ✗ | sws_setColorspaceDetails(scale->isws[0], inv_table, in_full, | |
840 | table, out_full, | ||
841 | brightness, contrast, saturation); | ||
842 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42367 times.
|
42367 | if (scale->isws[1]) |
843 | ✗ | sws_setColorspaceDetails(scale->isws[1], inv_table, in_full, | |
844 | table, out_full, | ||
845 | brightness, contrast, saturation); | ||
846 | |||
847 |
2/2✓ Branch 0 taken 17425 times.
✓ Branch 1 taken 24942 times.
|
42367 | out->color_range = out_full ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; |
848 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 42365 times.
|
42367 | if (scale->out_color_matrix != AVCOL_SPC_UNSPECIFIED) |
849 | 2 | out->colorspace = scale->out_color_matrix; | |
850 | } | ||
851 | |||
852 | // Sanity checks: | ||
853 | // 1. If the output is RGB, set the matrix coefficients to RGB. | ||
854 | // 2. If the output is not RGB and we've got the RGB/XYZ (identity) | ||
855 | // matrix configured, unset the matrix. | ||
856 | // In theory these should be in swscale itself as the AVFrame | ||
857 | // based API gets in, so that not every swscale API user has | ||
858 | // to go through duplicating such sanity checks. | ||
859 |
2/2✓ Branch 1 taken 13583 times.
✓ Branch 2 taken 28784 times.
|
42367 | if (av_pix_fmt_desc_get(out->format)->flags & AV_PIX_FMT_FLAG_RGB) |
860 | 13583 | out->colorspace = AVCOL_SPC_RGB; | |
861 |
2/2✓ Branch 0 taken 258 times.
✓ Branch 1 taken 28526 times.
|
28784 | else if (out->colorspace == AVCOL_SPC_RGB) |
862 | 258 | out->colorspace = AVCOL_SPC_UNSPECIFIED; | |
863 | |||
864 | 42367 | av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den, | |
865 | 42367 | (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w, | |
866 | 42367 | (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h, | |
867 | INT_MAX); | ||
868 | |||
869 |
2/4✓ Branch 0 taken 42367 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 42367 times.
|
42367 | if (scale->interlaced>0 || (scale->interlaced<0 && |
870 | ✗ | (in->flags & AV_FRAME_FLAG_INTERLACED))) { | |
871 | ✗ | ret = scale_field(scale, out, in, 0); | |
872 | ✗ | if (ret >= 0) | |
873 | ✗ | ret = scale_field(scale, out, in, 1); | |
874 | } else { | ||
875 | 42367 | ret = sws_scale_frame(scale->sws, out, in); | |
876 | } | ||
877 | |||
878 | 42367 | av_frame_free(&in); | |
879 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42367 times.
|
42367 | if (ret < 0) |
880 | ✗ | av_frame_free(frame_out); | |
881 | 42367 | return ret; | |
882 | } | ||
883 | |||
884 | 45731 | static int filter_frame(AVFilterLink *link, AVFrame *in) | |
885 | { | ||
886 | 45731 | AVFilterContext *ctx = link->dst; | |
887 | 45731 | AVFilterLink *outlink = ctx->outputs[0]; | |
888 | AVFrame *out; | ||
889 | int ret; | ||
890 | |||
891 | 45731 | ret = scale_frame(link, in, &out); | |
892 |
1/2✓ Branch 0 taken 45731 times.
✗ Branch 1 not taken.
|
45731 | if (out) |
893 | 45731 | return ff_filter_frame(outlink, out); | |
894 | |||
895 | ✗ | return ret; | |
896 | } | ||
897 | |||
898 | 5 | static int filter_frame_ref(AVFilterLink *link, AVFrame *in) | |
899 | { | ||
900 | 5 | ScaleContext *scale = link->dst->priv; | |
901 | 5 | AVFilterLink *outlink = link->dst->outputs[1]; | |
902 | int frame_changed; | ||
903 | |||
904 | 15 | frame_changed = in->width != link->w || | |
905 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | in->height != link->h || |
906 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | in->format != link->format || |
907 |
2/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
15 | in->sample_aspect_ratio.den != link->sample_aspect_ratio.den || |
908 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | in->sample_aspect_ratio.num != link->sample_aspect_ratio.num; |
909 | |||
910 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (frame_changed) { |
911 | ✗ | link->format = in->format; | |
912 | ✗ | link->w = in->width; | |
913 | ✗ | link->h = in->height; | |
914 | ✗ | link->sample_aspect_ratio.num = in->sample_aspect_ratio.num; | |
915 | ✗ | link->sample_aspect_ratio.den = in->sample_aspect_ratio.den; | |
916 | |||
917 | ✗ | config_props_ref(outlink); | |
918 | } | ||
919 | |||
920 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (scale->eval_mode == EVAL_MODE_FRAME) { |
921 | ✗ | scale->var_values[VAR_N] = link->frame_count_out; | |
922 | ✗ | scale->var_values[VAR_T] = TS2T(in->pts, link->time_base); | |
923 | #if FF_API_FRAME_PKT | ||
924 | FF_DISABLE_DEPRECATION_WARNINGS | ||
925 | ✗ | scale->var_values[VAR_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos; | |
926 | FF_ENABLE_DEPRECATION_WARNINGS | ||
927 | #endif | ||
928 | } | ||
929 | |||
930 | 5 | return ff_filter_frame(outlink, in); | |
931 | } | ||
932 | |||
933 | ✗ | static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, | |
934 | char *res, int res_len, int flags) | ||
935 | { | ||
936 | ✗ | ScaleContext *scale = ctx->priv; | |
937 | char *str_expr; | ||
938 | AVExpr **pexpr_ptr; | ||
939 | int ret, w, h; | ||
940 | |||
941 | ✗ | w = !strcmp(cmd, "width") || !strcmp(cmd, "w"); | |
942 | ✗ | h = !strcmp(cmd, "height") || !strcmp(cmd, "h"); | |
943 | |||
944 | ✗ | if (w || h) { | |
945 | ✗ | str_expr = w ? scale->w_expr : scale->h_expr; | |
946 | ✗ | pexpr_ptr = w ? &scale->w_pexpr : &scale->h_pexpr; | |
947 | |||
948 | ✗ | ret = scale_parse_expr(ctx, str_expr, pexpr_ptr, cmd, args); | |
949 | } else | ||
950 | ✗ | ret = AVERROR(ENOSYS); | |
951 | |||
952 | ✗ | if (ret < 0) | |
953 | ✗ | av_log(ctx, AV_LOG_ERROR, "Failed to process command. Continuing with existing parameters.\n"); | |
954 | |||
955 | ✗ | return ret; | |
956 | } | ||
957 | |||
958 | ✗ | static const AVClass *child_class_iterate(void **iter) | |
959 | { | ||
960 | ✗ | const AVClass *c = *iter ? NULL : sws_get_class(); | |
961 | ✗ | *iter = (void*)(uintptr_t)c; | |
962 | ✗ | return c; | |
963 | } | ||
964 | |||
965 | 6408 | static void *child_next(void *obj, void *prev) | |
966 | { | ||
967 | 6408 | ScaleContext *s = obj; | |
968 |
2/2✓ Branch 0 taken 4921 times.
✓ Branch 1 taken 1487 times.
|
6408 | if (!prev) |
969 | 4921 | return s->sws_opts; | |
970 | 1487 | return NULL; | |
971 | } | ||
972 | |||
973 | #define OFFSET(x) offsetof(ScaleContext, x) | ||
974 | #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM | ||
975 | #define TFLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM | ||
976 | |||
977 | static const AVOption scale_options[] = { | ||
978 | { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, .flags = TFLAGS }, | ||
979 | { "width", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, .flags = TFLAGS }, | ||
980 | { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, .flags = TFLAGS }, | ||
981 | { "height","Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, .flags = TFLAGS }, | ||
982 | { "flags", "Flags to pass to libswscale", OFFSET(flags_str), AV_OPT_TYPE_STRING, { .str = "" }, .flags = FLAGS }, | ||
983 | { "interl", "set interlacing", OFFSET(interlaced), AV_OPT_TYPE_BOOL, {.i64 = 0 }, -1, 1, FLAGS }, | ||
984 | { "size", "set video size", OFFSET(size_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, FLAGS }, | ||
985 | { "s", "set video size", OFFSET(size_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, FLAGS }, | ||
986 | { "in_color_matrix", "set input YCbCr type", OFFSET(in_color_matrix), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, AVCOL_SPC_NB-1, .flags = FLAGS, "color" }, | ||
987 | { "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, "color"}, | ||
988 | { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, 0, 0, FLAGS, "color" }, | ||
989 | { "bt601", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_SPC_BT470BG }, 0, 0, FLAGS, "color" }, | ||
990 | { "bt470", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_SPC_BT470BG }, 0, 0, FLAGS, "color" }, | ||
991 | { "smpte170m", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_SPC_BT470BG }, 0, 0, FLAGS, "color" }, | ||
992 | { "bt709", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_SPC_BT709 }, 0, 0, FLAGS, "color" }, | ||
993 | { "fcc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_SPC_FCC }, 0, 0, FLAGS, "color" }, | ||
994 | { "smpte240m", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_SPC_SMPTE240M }, 0, 0, FLAGS, "color" }, | ||
995 | { "bt2020", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_SPC_BT2020_NCL }, 0, 0, FLAGS, "color" }, | ||
996 | { "in_range", "set input color range", OFFSET( in_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, 2, FLAGS, "range" }, | ||
997 | { "out_range", "set output color range", OFFSET(out_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, 2, FLAGS, "range" }, | ||
998 | { "auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, 0, FLAGS, "range" }, | ||
999 | { "unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, 0, FLAGS, "range" }, | ||
1000 | { "full", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_JPEG}, 0, 0, FLAGS, "range" }, | ||
1001 | { "limited",NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_MPEG}, 0, 0, FLAGS, "range" }, | ||
1002 | { "jpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_JPEG}, 0, 0, FLAGS, "range" }, | ||
1003 | { "mpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_MPEG}, 0, 0, FLAGS, "range" }, | ||
1004 | { "tv", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_MPEG}, 0, 0, FLAGS, "range" }, | ||
1005 | { "pc", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_JPEG}, 0, 0, FLAGS, "range" }, | ||
1006 | { "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 }, | ||
1007 | { "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 }, | ||
1008 | { "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 }, | ||
1009 | { "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 }, | ||
1010 | { "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, "force_oar" }, | ||
1011 | { "disable", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, FLAGS, "force_oar" }, | ||
1012 | { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, "force_oar" }, | ||
1013 | { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, "force_oar" }, | ||
1014 | { "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 }, | ||
1015 | { "param0", "Scaler param 0", OFFSET(param[0]), AV_OPT_TYPE_DOUBLE, { .dbl = DBL_MAX }, -DBL_MAX, DBL_MAX, FLAGS }, | ||
1016 | { "param1", "Scaler param 1", OFFSET(param[1]), AV_OPT_TYPE_DOUBLE, { .dbl = DBL_MAX }, -DBL_MAX, DBL_MAX, FLAGS }, | ||
1017 | { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, {.i64 = EVAL_MODE_INIT}, 0, EVAL_MODE_NB-1, FLAGS, "eval" }, | ||
1018 | { "init", "eval expressions once during initialization", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_INIT}, .flags = FLAGS, .unit = "eval" }, | ||
1019 | { "frame", "eval expressions during initialization and per-frame", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = FLAGS, .unit = "eval" }, | ||
1020 | { NULL } | ||
1021 | }; | ||
1022 | |||
1023 | static const AVClass scale_class = { | ||
1024 | .class_name = "scale(2ref)", | ||
1025 | .item_name = av_default_item_name, | ||
1026 | .option = scale_options, | ||
1027 | .version = LIBAVUTIL_VERSION_INT, | ||
1028 | .category = AV_CLASS_CATEGORY_FILTER, | ||
1029 | .child_class_iterate = child_class_iterate, | ||
1030 | .child_next = child_next, | ||
1031 | }; | ||
1032 | |||
1033 | static const AVFilterPad avfilter_vf_scale_inputs[] = { | ||
1034 | { | ||
1035 | .name = "default", | ||
1036 | .type = AVMEDIA_TYPE_VIDEO, | ||
1037 | .filter_frame = filter_frame, | ||
1038 | }, | ||
1039 | }; | ||
1040 | |||
1041 | static const AVFilterPad avfilter_vf_scale_outputs[] = { | ||
1042 | { | ||
1043 | .name = "default", | ||
1044 | .type = AVMEDIA_TYPE_VIDEO, | ||
1045 | .config_props = config_props, | ||
1046 | }, | ||
1047 | }; | ||
1048 | |||
1049 | const AVFilter ff_vf_scale = { | ||
1050 | .name = "scale", | ||
1051 | .description = NULL_IF_CONFIG_SMALL("Scale the input video size and/or convert the image format."), | ||
1052 | .preinit = preinit, | ||
1053 | .init = init, | ||
1054 | .uninit = uninit, | ||
1055 | .priv_size = sizeof(ScaleContext), | ||
1056 | .priv_class = &scale_class, | ||
1057 | FILTER_INPUTS(avfilter_vf_scale_inputs), | ||
1058 | FILTER_OUTPUTS(avfilter_vf_scale_outputs), | ||
1059 | FILTER_QUERY_FUNC(query_formats), | ||
1060 | .process_command = process_command, | ||
1061 | }; | ||
1062 | |||
1063 | static const AVFilterPad avfilter_vf_scale2ref_inputs[] = { | ||
1064 | { | ||
1065 | .name = "default", | ||
1066 | .type = AVMEDIA_TYPE_VIDEO, | ||
1067 | .filter_frame = filter_frame, | ||
1068 | }, | ||
1069 | { | ||
1070 | .name = "ref", | ||
1071 | .type = AVMEDIA_TYPE_VIDEO, | ||
1072 | .filter_frame = filter_frame_ref, | ||
1073 | }, | ||
1074 | }; | ||
1075 | |||
1076 | static const AVFilterPad avfilter_vf_scale2ref_outputs[] = { | ||
1077 | { | ||
1078 | .name = "default", | ||
1079 | .type = AVMEDIA_TYPE_VIDEO, | ||
1080 | .config_props = config_props, | ||
1081 | .request_frame= request_frame, | ||
1082 | }, | ||
1083 | { | ||
1084 | .name = "ref", | ||
1085 | .type = AVMEDIA_TYPE_VIDEO, | ||
1086 | .config_props = config_props_ref, | ||
1087 | .request_frame= request_frame_ref, | ||
1088 | }, | ||
1089 | }; | ||
1090 | |||
1091 | const AVFilter ff_vf_scale2ref = { | ||
1092 | .name = "scale2ref", | ||
1093 | .description = NULL_IF_CONFIG_SMALL("Scale the input video size and/or convert the image format to the given reference."), | ||
1094 | .preinit = preinit, | ||
1095 | .init = init, | ||
1096 | .uninit = uninit, | ||
1097 | .priv_size = sizeof(ScaleContext), | ||
1098 | .priv_class = &scale_class, | ||
1099 | FILTER_INPUTS(avfilter_vf_scale2ref_inputs), | ||
1100 | FILTER_OUTPUTS(avfilter_vf_scale2ref_outputs), | ||
1101 | FILTER_QUERY_FUNC(query_formats), | ||
1102 | .process_command = process_command, | ||
1103 | }; | ||
1104 |