By using preinit, the SwrContext already exists directly after allocating the filter, so that the filter's AVClass's child_next becomes usable for setting options with the AV_OPT_SEARCH_CHILDREN search flag. This means that it is no longer necessary to use the init_dict callback for this filter. Furthermore, the earlier code did not abide by the documentation of the init_dict callback at all: Instead of only returning the options that have not been recognized it always returned all options on any av_opt_set() error and errored out in this case; yet if the error was just caused by an unrecognized option, it should not error out at all and instead return said option. This behaviour has been inherited by avfilter_init_dict(), contradicting its documentation. This is also fixed by this commit.
Showing the changes to libavfilter (1 of 1 file). Show all
Unified · Split
| @@ -43,31 +43,16 @@ typedef struct AResampleContext { · 42 unmodified lines | ||
| 43 | 43 | int more_data; |
| 44 | 44 | } AResampleContext; |
| 45 | 45 | |
| 46 | −static av_cold int init_dict(AVFilterContext *ctx, AVDictionary **opts) | |
| 46 | +static av_cold int preinit(AVFilterContext *ctx) | |
| 47 | 47 | { |
| 48 | 48 | AResampleContext *aresample = ctx->priv; |
| 49 | − int ret = 0; | |
| 50 | 49 | |
| 51 | 50 | aresample->next_pts = AV_NOPTS_VALUE; |
| 52 | 51 | aresample->swr = swr_alloc(); |
| 53 | − if (!aresample->swr) { | |
| 54 | − ret = AVERROR(ENOMEM); | |
| 55 | − goto end; | |
| 56 | − } | |
| 57 | − | |
| 58 | − if (opts) { | |
| 59 | − AVDictionaryEntry *e = NULL; | |
| 52 | + if (!aresample->swr) | |
| 53 | + return AVERROR(ENOMEM); | |
| 60 | 54 | |
| 61 | − while ((e = av_dict_get(*opts, "", e, AV_DICT_IGNORE_SUFFIX))) { | |
| 62 | − if ((ret = av_opt_set(aresample->swr, e->key, e->value, 0)) < 0) | |
| 63 | − goto end; | |
| 64 | − } | |
| 65 | − av_dict_free(opts); | |
| 66 | − } | |
| 67 | − if (aresample->sample_rate_arg > 0) | |
| 68 | − av_opt_set_int(aresample->swr, "osr", aresample->sample_rate_arg, 0); | |
| 69 | −end: | |
| 70 | − return ret; | |
| 55 | + return 0; | |
| 71 | 56 | } |
| 72 | 57 | |
| 73 | 58 | static av_cold void uninit(AVFilterContext *ctx) |
| @@ -90,6 +75,8 @@ static int query_formats(AVFilterContext *ctx) · 16 unmodified lines | ||
| 90 | 75 | AVFilterChannelLayouts *in_layouts, *out_layouts; |
| 91 | 76 | int ret; |
| 92 | 77 | |
| 78 | + if (aresample->sample_rate_arg > 0) | |
| 79 | + av_opt_set_int(aresample->swr, "osr", aresample->sample_rate_arg, 0); | |
| 93 | 80 | av_opt_get_sample_fmt(aresample->swr, "osf", 0, &out_format); |
| 94 | 81 | av_opt_get_int(aresample->swr, "osr", 0, &out_rate); |
| 95 | 82 | av_opt_get_int(aresample->swr, "ocl", 0, &out_layout); |
| @@ -343,7 +330,7 @@ static const AVFilterPad aresample_outputs[] = { · 247 unmodified lines | ||
| 343 | 330 | const AVFilter ff_af_aresample = { |
| 344 | 331 | .name = "aresample", |
| 345 | 332 | .description = NULL_IF_CONFIG_SMALL("Resample audio data."), |
| 346 | − .init_dict = init_dict, | |
| 333 | + .preinit = preinit, | |
| 347 | 334 | .uninit = uninit, |
| 348 | 335 | .query_formats = query_formats, |
| 349 | 336 | .priv_size = sizeof(AResampleContext), |