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 | int more_data; | 43 | int more_data; |
| 44 | } AResampleContext; | 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 | AResampleContext *aresample = ctx->priv; | 48 | AResampleContext *aresample = ctx->priv; |
| 49 | int ret = 0; | ||
| 50 | 49 | ||
| 51 | aresample->next_pts = AV_NOPTS_VALUE; | 50 | aresample->next_pts = AV_NOPTS_VALUE; |
| 52 | aresample->swr = swr_alloc(); | 51 | aresample->swr = swr_alloc(); |
| 53 | if (!aresample->swr) { | 52 | if (!aresample->swr) |
| 54 | ret = AVERROR(ENOMEM); | 53 | return AVERROR(ENOMEM); |
| 55 | goto end; | ||
| 56 | } | ||
| 57 | |||
| 58 | if (opts) { | ||
| 59 | AVDictionaryEntry *e = NULL; | ||
| 60 | 54 | ||
| 61 | while ((e = av_dict_get(*opts, "", e, AV_DICT_IGNORE_SUFFIX))) { | 55 | return 0; |
| 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; | ||
| 71 | } | 56 | } |
| 72 | 57 | ||
| 73 | static av_cold void uninit(AVFilterContext *ctx) | 58 | static av_cold void uninit(AVFilterContext *ctx) |
| @@ -90,6 +75,8 @@ static int query_formats(AVFilterContext *ctx) · 16 unmodified lines | |||
| 90 | AVFilterChannelLayouts *in_layouts, *out_layouts; | 75 | AVFilterChannelLayouts *in_layouts, *out_layouts; |
| 91 | int ret; | 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 | av_opt_get_sample_fmt(aresample->swr, "osf", 0, &out_format); | 80 | av_opt_get_sample_fmt(aresample->swr, "osf", 0, &out_format); |
| 94 | av_opt_get_int(aresample->swr, "osr", 0, &out_rate); | 81 | av_opt_get_int(aresample->swr, "osr", 0, &out_rate); |
| 95 | av_opt_get_int(aresample->swr, "ocl", 0, &out_layout); | 82 | av_opt_get_int(aresample->swr, "ocl", 0, &out_layout); |
| @@ -343,7 +330,7 @@ static const AVFilterPad aresample_outputs[] = { · 247 unmodified lines | |||
| 343 | const AVFilter ff_af_aresample = { | 330 | const AVFilter ff_af_aresample = { |
| 344 | .name = "aresample", | 331 | .name = "aresample", |
| 345 | .description = NULL_IF_CONFIG_SMALL("Resample audio data."), | 332 | .description = NULL_IF_CONFIG_SMALL("Resample audio data."), |
| 346 | .init_dict = init_dict, | 333 | .preinit = preinit, |
| 347 | .uninit = uninit, | 334 | .uninit = uninit, |
| 348 | .query_formats = query_formats, | 335 | .query_formats = query_formats, |
| 349 | .priv_size = sizeof(AResampleContext), | 336 | .priv_size = sizeof(AResampleContext), |