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.
Showing the changes to libavfilter (1 of 1 file). Show all
Unified · Split
| @@ -23,6 +23,7 @@ · 22 unmodified lines | |||
| 23 | * scale video filter | 23 | * scale video filter |
| 24 | */ | 24 | */ |
| 25 | 25 | ||
| 26 | #include <float.h> | ||
| 26 | #include <stdio.h> | 27 | #include <stdio.h> |
| 27 | #include <string.h> | 28 | #include <string.h> |
| 28 | 29 | ||
| @@ -107,7 +108,8 @@ typedef struct ScaleContext { · 78 unmodified lines | |||
| 107 | const AVClass *class; | 108 | const AVClass *class; |
| 108 | struct SwsContext *sws; ///< software scaler context | 109 | struct SwsContext *sws; ///< software scaler context |
| 109 | struct SwsContext *isws[2]; ///< software scaler context for interlaced material | 110 | 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; | ||
| 111 | 113 | ||
| 112 | /** | 114 | /** |
| 113 | * New dimensions. Special values are: | 115 | * New dimensions. Special values are: |
| @@ -117,7 +119,6 @@ typedef struct ScaleContext { · 3 unmodified lines | |||
| 117 | */ | 119 | */ |
| 118 | int w, h; | 120 | int w, h; |
| 119 | char *size_str; | 121 | char *size_str; |
| 120 | unsigned int flags; ///sws flags | ||
| 121 | double param[2]; // sws params | 122 | double param[2]; // sws params |
| 122 | 123 | ||
| 123 | int hsub, vsub; ///< chroma subsampling | 124 | int hsub, vsub; ///< chroma subsampling |
| @@ -268,11 +269,29 @@ revert: · 144 unmodified lines | |||
| 268 | return ret; | 269 | return ret; |
| 269 | } | 270 | } |
| 270 | 271 | ||
| 271 | static av_cold int init_dict(AVFilterContext *ctx, AVDictionary **opts) | 272 | static av_cold int preinit(AVFilterContext *ctx) |
| 272 | { | 273 | { |
| 273 | ScaleContext *scale = ctx->priv; | 274 | ScaleContext *scale = ctx->priv; |
| 274 | int ret; | 275 | int ret; |
| 275 | 276 | ||
| 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 | |||
| 276 | if (scale->size_str && (scale->w_expr || scale->h_expr)) { | 295 | if (scale->size_str && (scale->w_expr || scale->h_expr)) { |
| 277 | av_log(ctx, AV_LOG_ERROR, | 296 | av_log(ctx, AV_LOG_ERROR, |
| 278 | "Size and width/height expressions cannot be set at the same time.\n"); | 297 | "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 | |||
| 310 | av_log(ctx, AV_LOG_VERBOSE, "w:%s h:%s flags:'%s' interl:%d\n", | 329 | av_log(ctx, AV_LOG_VERBOSE, "w:%s h:%s flags:'%s' interl:%d\n", |
| 311 | scale->w_expr, scale->h_expr, (char *)av_x_if_null(scale->flags_str, ""), scale->interlaced); | 330 | scale->w_expr, scale->h_expr, (char *)av_x_if_null(scale->flags_str, ""), scale->interlaced); |
| 312 | 331 | ||
| 313 | scale->flags = 0; | ||
| 314 | |||
| 315 | if (scale->flags_str && *scale->flags_str) { | 332 | if (scale->flags_str && *scale->flags_str) { |
| 316 | const AVClass *class = sws_get_class(); | 333 | ret = av_opt_set(scale->sws_opts, "sws_flags", scale->flags_str, 0); |
| 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); | ||
| 320 | if (ret < 0) | 334 | if (ret < 0) |
| 321 | return ret; | 335 | return ret; |
| 322 | } | 336 | } |
| 323 | scale->opts = *opts; | 337 | |
| 324 | *opts = NULL; | 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); | ||
| 325 | 352 | ||
| 326 | scale->in_frame_range = AVCOL_RANGE_UNSPECIFIED; | 353 | scale->in_frame_range = AVCOL_RANGE_UNSPECIFIED; |
| 327 | 354 | ||
| @@ -334,11 +361,11 @@ static av_cold void uninit(AVFilterContext *ctx) · 6 unmodified lines | |||
| 334 | av_expr_free(scale->w_pexpr); | 361 | av_expr_free(scale->w_pexpr); |
| 335 | av_expr_free(scale->h_pexpr); | 362 | av_expr_free(scale->h_pexpr); |
| 336 | scale->w_pexpr = scale->h_pexpr = NULL; | 363 | scale->w_pexpr = scale->h_pexpr = NULL; |
| 364 | sws_freeContext(scale->sws_opts); | ||
| 337 | sws_freeContext(scale->sws); | 365 | sws_freeContext(scale->sws); |
| 338 | sws_freeContext(scale->isws[0]); | 366 | sws_freeContext(scale->isws[0]); |
| 339 | sws_freeContext(scale->isws[1]); | 367 | sws_freeContext(scale->isws[1]); |
| 340 | scale->sws = NULL; | 368 | scale->sws = NULL; |
| 341 | av_dict_free(&scale->opts); | ||
| 342 | } | 369 | } |
| 343 | 370 | ||
| 344 | static int query_formats(AVFilterContext *ctx) | 371 | static int query_formats(AVFilterContext *ctx) |
| @@ -486,6 +513,7 @@ static int config_props(AVFilterLink *outlink) · 141 unmodified lines | |||
| 486 | enum AVPixelFormat outfmt = outlink->format; | 513 | enum AVPixelFormat outfmt = outlink->format; |
| 487 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); | 514 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); |
| 488 | ScaleContext *scale = ctx->priv; | 515 | ScaleContext *scale = ctx->priv; |
| 516 | uint8_t *flags_val = NULL; | ||
| 489 | int ret; | 517 | int ret; |
| 490 | 518 | ||
| 491 | if ((ret = scale_eval_dimensions(ctx)) < 0) | 519 | if ((ret = scale_eval_dimensions(ctx)) < 0) |
| @@ -534,16 +562,16 @@ static int config_props(AVFilterLink *outlink) · 42 unmodified lines | |||
| 534 | return AVERROR(ENOMEM); | 562 | return AVERROR(ENOMEM); |
| 535 | *swscs[i] = s; | 563 | *swscs[i] = s; |
| 536 | 564 | ||
| 565 | ret = av_opt_copy(s, scale->sws_opts); | ||
| 566 | if (ret < 0) | ||
| 567 | return ret; | ||
| 568 | |||
| 537 | av_opt_set_int(s, "srcw", inlink0 ->w, 0); | 569 | av_opt_set_int(s, "srcw", inlink0 ->w, 0); |
| 538 | av_opt_set_int(s, "srch", inlink0 ->h >> !!i, 0); | 570 | av_opt_set_int(s, "srch", inlink0 ->h >> !!i, 0); |
| 539 | av_opt_set_int(s, "src_format", inlink0->format, 0); | 571 | av_opt_set_int(s, "src_format", inlink0->format, 0); |
| 540 | av_opt_set_int(s, "dstw", outlink->w, 0); | 572 | av_opt_set_int(s, "dstw", outlink->w, 0); |
| 541 | av_opt_set_int(s, "dsth", outlink->h >> !!i, 0); | 573 | av_opt_set_int(s, "dsth", outlink->h >> !!i, 0); |
| 542 | av_opt_set_int(s, "dst_format", outfmt, 0); | 574 | 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); | ||
| 547 | if (scale->in_range != AVCOL_RANGE_UNSPECIFIED) | 575 | if (scale->in_range != AVCOL_RANGE_UNSPECIFIED) |
| 548 | av_opt_set_int(s, "src_range", | 576 | av_opt_set_int(s, "src_range", |
| 549 | scale->in_range == AVCOL_RANGE_JPEG, 0); | 577 | scale->in_range == AVCOL_RANGE_JPEG, 0); |
| @@ -554,13 +582,6 @@ static int config_props(AVFilterLink *outlink) · 4 unmodified lines | |||
| 554 | av_opt_set_int(s, "dst_range", | 582 | av_opt_set_int(s, "dst_range", |
| 555 | scale->out_range == AVCOL_RANGE_JPEG, 0); | 583 | scale->out_range == AVCOL_RANGE_JPEG, 0); |
| 556 | 584 | ||
| 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 | } | ||
| 564 | /* Override YUV420P default settings to have the correct (MPEG-2) chroma positions | 585 | /* Override YUV420P default settings to have the correct (MPEG-2) chroma positions |
| 565 | * MPEG-2 chroma positions are used by convention | 586 | * MPEG-2 chroma positions are used by convention |
| 566 | * XXX: support other 4:2:0 pixel formats */ | 587 | * XXX: support other 4:2:0 pixel formats */ |
| @@ -589,12 +610,17 @@ static int config_props(AVFilterLink *outlink) · 22 unmodified lines | |||
| 589 | } else | 610 | } else |
| 590 | outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio; | 611 | outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio; |
| 591 | 612 | ||
| 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", | ||
| 593 | inlink ->w, inlink ->h, av_get_pix_fmt_name( inlink->format), | 617 | inlink ->w, inlink ->h, av_get_pix_fmt_name( inlink->format), |
| 594 | inlink->sample_aspect_ratio.num, inlink->sample_aspect_ratio.den, | 618 | inlink->sample_aspect_ratio.num, inlink->sample_aspect_ratio.den, |
| 595 | outlink->w, outlink->h, av_get_pix_fmt_name(outlink->format), | 619 | outlink->w, outlink->h, av_get_pix_fmt_name(outlink->format), |
| 596 | outlink->sample_aspect_ratio.num, outlink->sample_aspect_ratio.den, | 620 | outlink->sample_aspect_ratio.num, outlink->sample_aspect_ratio.den, |
| 597 | scale->flags); | 621 | flags_val); |
| 622 | av_freep(&flags_val); | ||
| 623 | |||
| 598 | return 0; | 624 | return 0; |
| 599 | 625 | ||
| 600 | fail: | 626 | fail: |
| @@ -927,6 +953,14 @@ static const AVClass *child_class_iterate(void **iter) · 326 unmodified lines | |||
| 927 | return c; | 953 | return c; |
| 928 | } | 954 | } |
| 929 | 955 | ||
| 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 | |||
| 930 | #define OFFSET(x) offsetof(ScaleContext, x) | 964 | #define OFFSET(x) offsetof(ScaleContext, x) |
| 931 | #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM | 965 | #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM |
| 932 | #define TFLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM | 966 | #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 | |||
| 969 | { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, "force_oar" }, | 1003 | { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, "force_oar" }, |
| 970 | { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, "force_oar" }, | 1004 | { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, "force_oar" }, |
| 971 | { "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 }, | 1005 | { "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 }, | 1006 | { "param0", "Scaler param 0", OFFSET(param[0]), AV_OPT_TYPE_DOUBLE, { .dbl = DBL_MAX }, -DBL_MAX, DBL_MAX, FLAGS }, |
| 973 | { "param1", "Scaler param 1", OFFSET(param[1]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, FLAGS }, | 1007 | { "param1", "Scaler param 1", OFFSET(param[1]), AV_OPT_TYPE_DOUBLE, { .dbl = DBL_MAX }, -DBL_MAX, DBL_MAX, FLAGS }, |
| 974 | { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, {.i64 = EVAL_MODE_INIT}, 0, EVAL_MODE_NB-1, FLAGS, "eval" }, | 1008 | { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, {.i64 = EVAL_MODE_INIT}, 0, EVAL_MODE_NB-1, FLAGS, "eval" }, |
| 975 | { "init", "eval expressions once during initialization", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_INIT}, .flags = FLAGS, .unit = "eval" }, | 1009 | { "init", "eval expressions once during initialization", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_INIT}, .flags = FLAGS, .unit = "eval" }, |
| 976 | { "frame", "eval expressions during initialization and per-frame", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = FLAGS, .unit = "eval" }, | 1010 | { "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 | |||
| 984 | .version = LIBAVUTIL_VERSION_INT, | 1018 | .version = LIBAVUTIL_VERSION_INT, |
| 985 | .category = AV_CLASS_CATEGORY_FILTER, | 1019 | .category = AV_CLASS_CATEGORY_FILTER, |
| 986 | .child_class_iterate = child_class_iterate, | 1020 | .child_class_iterate = child_class_iterate, |
| 1021 | .child_next = child_next, | ||
| 987 | }; | 1022 | }; |
| 988 | 1023 | ||
| 989 | static const AVFilterPad avfilter_vf_scale_inputs[] = { | 1024 | static const AVFilterPad avfilter_vf_scale_inputs[] = { |
| @@ -1005,7 +1040,8 @@ static const AVFilterPad avfilter_vf_scale_outputs[] = { · 15 unmodified lines | |||
| 1005 | const AVFilter ff_vf_scale = { | 1040 | const AVFilter ff_vf_scale = { |
| 1006 | .name = "scale", | 1041 | .name = "scale", |
| 1007 | .description = NULL_IF_CONFIG_SMALL("Scale the input video size and/or convert the image format."), | 1042 | .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, | ||
| 1009 | .uninit = uninit, | 1045 | .uninit = uninit, |
| 1010 | .priv_size = sizeof(ScaleContext), | 1046 | .priv_size = sizeof(ScaleContext), |
| 1011 | .priv_class = &scale_class, | 1047 | .priv_class = &scale_class, |
| @@ -1046,7 +1082,8 @@ static const AVFilterPad avfilter_vf_scale2ref_outputs[] = { · 34 unmodified lines | |||
| 1046 | const AVFilter ff_vf_scale2ref = { | 1082 | const AVFilter ff_vf_scale2ref = { |
| 1047 | .name = "scale2ref", | 1083 | .name = "scale2ref", |
| 1048 | .description = NULL_IF_CONFIG_SMALL("Scale the input video size and/or convert the image format to the given reference."), | 1084 | .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, | ||
| 1050 | .uninit = uninit, | 1087 | .uninit = uninit, |
| 1051 | .priv_size = sizeof(ScaleContext), | 1088 | .priv_size = sizeof(ScaleContext), |
| 1052 | .priv_class = &scale_class, | 1089 | .priv_class = &scale_class, |