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