History

lavfi/vf_scale: allow passing options to swscale directly

Avoid using the dictionary mechanism, which is non-introspectable. As this is the only user of AVFilter.init_dict(), this callback can now be removed.

Anton Khirnov committed 3 years ago

Commit 018a8b91 parent 260f3911 file · +66 −29Browse files

Showing the changes to libavfilter (1 of 1 file). Show all

Unified · Split

libavfilter/vf_scale.c+66−29
@@ -23,6 +23,7 @@ · 22 unmodified lines
2323 * scale video filter
2424 */
2525
26+#include <float.h>
2627 #include <stdio.h>
2728 #include <string.h>
2829
@@ -107,7 +108,8 @@ typedef struct ScaleContext { · 78 unmodified lines
107108 const AVClass *class;
108109 struct SwsContext *sws; ///< software scaler context
109110 struct SwsContext *isws[2]; ///< software scaler context for interlaced material
110− AVDictionary *opts;
111+ // context used for forwarding options to sws
112+ struct SwsContext *sws_opts;
111113
112114 /**
113115 * New dimensions. Special values are:
@@ -117,7 +119,6 @@ typedef struct ScaleContext { · 3 unmodified lines
117119 */
118120 int w, h;
119121 char *size_str;
120− unsigned int flags; ///sws flags
121122 double param[2]; // sws params
122123
123124 int hsub, vsub; ///< chroma subsampling
@@ -268,11 +269,29 @@ revert: · 144 unmodified lines
268269 return ret;
269270 }
270271
271−static av_cold int init_dict(AVFilterContext *ctx, AVDictionary **opts)
272+static av_cold int preinit(AVFilterContext *ctx)
272273 {
273274 ScaleContext *scale = ctx->priv;
274275 int ret;
275276
277+ scale->sws_opts = sws_alloc_context();
278+ if (!scale->sws_opts)
279+ return AVERROR(ENOMEM);
280+
281+ // set threads=0, so we can later check whether the user modified it
282+ ret = av_opt_set_int(scale->sws_opts, "threads", 0, 0);
283+ if (ret < 0)
284+ return ret;
285+
286+ return 0;
287+}
288+
289+static av_cold int init(AVFilterContext *ctx)
290+{
291+ ScaleContext *scale = ctx->priv;
292+ int64_t threads;
293+ int ret;
294+
276295 if (scale->size_str && (scale->w_expr || scale->h_expr)) {
277296 av_log(ctx, AV_LOG_ERROR,
278297 "Size and width/height expressions cannot be set at the same time.\n");
@@ -310,18 +329,26 @@ static av_cold int init_dict(AVFilterContext *ctx, AVDictionary **opts) · 31 unmodified lines
310329 av_log(ctx, AV_LOG_VERBOSE, "w:%s h:%s flags:'%s' interl:%d\n",
311330 scale->w_expr, scale->h_expr, (char *)av_x_if_null(scale->flags_str, ""), scale->interlaced);
312331
313− scale->flags = 0;
314−
315332 if (scale->flags_str && *scale->flags_str) {
316− const AVClass *class = sws_get_class();
317− const AVOption *o = av_opt_find(&class, "sws_flags", NULL, 0,
318− AV_OPT_SEARCH_FAKE_OBJ);
319− int ret = av_opt_eval_flags(&class, o, scale->flags_str, &scale->flags);
333+ ret = av_opt_set(scale->sws_opts, "sws_flags", scale->flags_str, 0);
320334 if (ret < 0)
321335 return ret;
322336 }
323− scale->opts = *opts;
324− *opts = NULL;
337+
338+ for (int i = 0; i < FF_ARRAY_ELEMS(scale->param); i++)
339+ if (scale->param[i] != DBL_MAX) {
340+ ret = av_opt_set_double(scale->sws_opts, i ? "param1" : "param0",
341+ scale->param[i], 0);
342+ if (ret < 0)
343+ return ret;
344+ }
345+
346+ // use generic thread-count if the user did not set it explicitly
347+ ret = av_opt_get_int(scale->sws_opts, "threads", 0, &threads);
348+ if (ret < 0)
349+ return ret;
350+ if (!threads)
351+ av_opt_set_int(scale->sws_opts, "threads", ff_filter_get_nb_threads(ctx), 0);
325352
326353 scale->in_frame_range = AVCOL_RANGE_UNSPECIFIED;
327354
@@ -334,11 +361,11 @@ static av_cold void uninit(AVFilterContext *ctx) · 6 unmodified lines
334361 av_expr_free(scale->w_pexpr);
335362 av_expr_free(scale->h_pexpr);
336363 scale->w_pexpr = scale->h_pexpr = NULL;
364+ sws_freeContext(scale->sws_opts);
337365 sws_freeContext(scale->sws);
338366 sws_freeContext(scale->isws[0]);
339367 sws_freeContext(scale->isws[1]);
340368 scale->sws = NULL;
341− av_dict_free(&scale->opts);
342369 }
343370
344371 static int query_formats(AVFilterContext *ctx)
@@ -486,6 +513,7 @@ static int config_props(AVFilterLink *outlink) · 141 unmodified lines
486513 enum AVPixelFormat outfmt = outlink->format;
487514 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
488515 ScaleContext *scale = ctx->priv;
516+ uint8_t *flags_val = NULL;
489517 int ret;
490518
491519 if ((ret = scale_eval_dimensions(ctx)) < 0)
@@ -534,16 +562,16 @@ static int config_props(AVFilterLink *outlink) · 42 unmodified lines
534562 return AVERROR(ENOMEM);
535563 *swscs[i] = s;
536564
565+ ret = av_opt_copy(s, scale->sws_opts);
566+ if (ret < 0)
567+ return ret;
568+
537569 av_opt_set_int(s, "srcw", inlink0 ->w, 0);
538570 av_opt_set_int(s, "srch", inlink0 ->h >> !!i, 0);
539571 av_opt_set_int(s, "src_format", inlink0->format, 0);
540572 av_opt_set_int(s, "dstw", outlink->w, 0);
541573 av_opt_set_int(s, "dsth", outlink->h >> !!i, 0);
542574 av_opt_set_int(s, "dst_format", outfmt, 0);
543− av_opt_set_int(s, "sws_flags", scale->flags, 0);
544− av_opt_set_int(s, "param0", scale->param[0], 0);
545− av_opt_set_int(s, "param1", scale->param[1], 0);
546− av_opt_set_int(s, "threads", ff_filter_get_nb_threads(ctx), 0);
547575 if (scale->in_range != AVCOL_RANGE_UNSPECIFIED)
548576 av_opt_set_int(s, "src_range",
549577 scale->in_range == AVCOL_RANGE_JPEG, 0);
@@ -554,13 +582,6 @@ static int config_props(AVFilterLink *outlink) · 4 unmodified lines
554582 av_opt_set_int(s, "dst_range",
555583 scale->out_range == AVCOL_RANGE_JPEG, 0);
556584
557− if (scale->opts) {
558− const AVDictionaryEntry *e = NULL;
559− while ((e = av_dict_iterate(scale->opts, e))) {
560− if ((ret = av_opt_set(s, e->key, e->value, 0)) < 0)
561− return ret;
562− }
563− }
564585 /* Override YUV420P default settings to have the correct (MPEG-2) chroma positions
565586 * MPEG-2 chroma positions are used by convention
566587 * XXX: support other 4:2:0 pixel formats */
@@ -589,12 +610,17 @@ static int config_props(AVFilterLink *outlink) · 22 unmodified lines
589610 } else
590611 outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio;
591612
592− 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:0x%0x\n",
613+ if (scale->sws)
614+ av_opt_get(scale->sws, "sws_flags", 0, &flags_val);
615+
616+ 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",
593617 inlink ->w, inlink ->h, av_get_pix_fmt_name( inlink->format),
594618 inlink->sample_aspect_ratio.num, inlink->sample_aspect_ratio.den,
595619 outlink->w, outlink->h, av_get_pix_fmt_name(outlink->format),
596620 outlink->sample_aspect_ratio.num, outlink->sample_aspect_ratio.den,
597− scale->flags);
621+ flags_val);
622+ av_freep(&flags_val);
623+
598624 return 0;
599625
600626 fail:
@@ -927,6 +953,14 @@ static const AVClass *child_class_iterate(void **iter) · 326 unmodified lines
927953 return c;
928954 }
929955
956+static void *child_next(void *obj, void *prev)
957+{
958+ ScaleContext *s = obj;
959+ if (!prev)
960+ return s->sws_opts;
961+ return NULL;
962+}
963+
930964 #define OFFSET(x) offsetof(ScaleContext, x)
931965 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
932966 #define TFLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
@@ -969,8 +1003,8 @@ static const AVOption scale_options[] = { · 36 unmodified lines
9691003 { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, "force_oar" },
9701004 { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, "force_oar" },
9711005 { "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 },
972− { "param0", "Scaler param 0", OFFSET(param[0]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, FLAGS },
973− { "param1", "Scaler param 1", OFFSET(param[1]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, FLAGS },
1006+ { "param0", "Scaler param 0", OFFSET(param[0]), AV_OPT_TYPE_DOUBLE, { .dbl = DBL_MAX }, -DBL_MAX, DBL_MAX, FLAGS },
1007+ { "param1", "Scaler param 1", OFFSET(param[1]), AV_OPT_TYPE_DOUBLE, { .dbl = DBL_MAX }, -DBL_MAX, DBL_MAX, FLAGS },
9741008 { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, {.i64 = EVAL_MODE_INIT}, 0, EVAL_MODE_NB-1, FLAGS, "eval" },
9751009 { "init", "eval expressions once during initialization", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_INIT}, .flags = FLAGS, .unit = "eval" },
9761010 { "frame", "eval expressions during initialization and per-frame", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = FLAGS, .unit = "eval" },
@@ -984,6 +1018,7 @@ static const AVClass scale_class = { · 7 unmodified lines
9841018 .version = LIBAVUTIL_VERSION_INT,
9851019 .category = AV_CLASS_CATEGORY_FILTER,
9861020 .child_class_iterate = child_class_iterate,
1021+ .child_next = child_next,
9871022 };
9881023
9891024 static const AVFilterPad avfilter_vf_scale_inputs[] = {
@@ -1005,7 +1040,8 @@ static const AVFilterPad avfilter_vf_scale_outputs[] = { · 15 unmodified lines
10051040 const AVFilter ff_vf_scale = {
10061041 .name = "scale",
10071042 .description = NULL_IF_CONFIG_SMALL("Scale the input video size and/or convert the image format."),
1008− .init_dict = init_dict,
1043+ .preinit = preinit,
1044+ .init = init,
10091045 .uninit = uninit,
10101046 .priv_size = sizeof(ScaleContext),
10111047 .priv_class = &scale_class,
@@ -1046,7 +1082,8 @@ static const AVFilterPad avfilter_vf_scale2ref_outputs[] = { · 34 unmodified lines
10461082 const AVFilter ff_vf_scale2ref = {
10471083 .name = "scale2ref",
10481084 .description = NULL_IF_CONFIG_SMALL("Scale the input video size and/or convert the image format to the given reference."),
1049− .init_dict = init_dict,
1085+ .preinit = preinit,
1086+ .init = init,
10501087 .uninit = uninit,
10511088 .priv_size = sizeof(ScaleContext),
10521089 .priv_class = &scale_class,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t