Thank you for reviewing @ #2781. > I do not think this option should be global.
I agree that public global options should not be added (or removed :) w/o discussion. > Possibly, the good solution may be to extend the "sws_flags=" feature > to allow to set more graph options from the graph description. There are some reasons why I chose to add new ones to the AVFilter context but not to extend the "swr_flags=", 1. The function swap_samplerates_on_filter() in avfiltergraph.c receives a pointer to AVFilterContext 2. Less elegant to pack a single value of the existing option with additional bit-chunks But prepending of explicit aresample will be required because of auto-inserted one cannot be received the info. -af "aresample=osr_fallback_method=highest,aformat=sample_rates=..." > I would rather not have the numeric values of the option exposed to the > user, only symbolic constants. > Re-aligning other lines is normally done in a separate patch, if ever. > I think this shoulw be "case 0" (except see below) and default should > trigger an assert failure. > Magic constants like that are not good design, they need to be expressed > by an enum. > Jumping from one case clause to another does not look like an acceptable > use of goto in readable code. Worth obeying :) Finally, it's obvious "osr_fallback_method" is lengthy and ugly :( Please suggest more concise and plain alternatives. --- libavfilter/avfilter.c | 6 ++++++ libavfilter/avfilter.h | 11 +++++++++++ libavfilter/avfiltergraph.c | 27 ++++++++++++++++++++++++++- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index b431990..0d467ec 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -665,6 +665,12 @@ static const AVOption avfilter_options[] = { { "enable", "set enable expression", OFFSET(enable_str), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS }, { "threads", "Allowed number of threads", OFFSET(nb_threads), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, + { "osr_fallback_method", "Output sample rate fallback method when no exact match found", OFFSET(osr_fallback_method), AV_OPT_TYPE_INT, + { .i64 = AVOSRFB_CLOSEST }, AVOSRFB_CLOSEST, AVOSRFB_HIGHEST, FLAGS, "osr_fallback_method" }, + { "closest", "to the closest one, regardless of higher or lower", 0, AV_OPT_TYPE_CONST, { .i64 = AVOSRFB_CLOSEST }, 0, 0, FLAGS, "osr_fallback_method" }, + { "higher", "to the closest higher one", 0, AV_OPT_TYPE_CONST, { .i64 = AVOSRFB_HIGHER }, 0, 0, FLAGS, "osr_fallback_method" }, + { "twice_higher", "to the closest twice higher one", 0, AV_OPT_TYPE_CONST, { .i64 = AVOSRFB_TWICE_HIGHER }, 0, 0, FLAGS, "osr_fallback_method" }, + { "highest", "to the highest one", 0, AV_OPT_TYPE_CONST, { .i64 = AVOSRFB_HIGHEST }, 0, 0, FLAGS, "osr_fallback_method" }, { NULL }, }; diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index b56615c..3eb455f 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -384,6 +384,17 @@ struct AVFilterContext { int nb_threads; /** + * Output sample rate fallback method when no exact match found in the next + * filter's available input sample rates. + */ + enum { + AVOSRFB_CLOSEST = 0, ///< to the closest one, regardless of higher or lower + AVOSRFB_HIGHER, ///< to the closest higher one + AVOSRFB_TWICE_HIGHER, ///< to the closest twice higher one + AVOSRFB_HIGHEST, ///< to the highest one + } osr_fallback_method; + + /** * Ready status of the filter. * A non-0 value means that the filter needs activating; * a higher value suggests a more urgent activation. diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index 534c670..0f193ec 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -874,7 +874,32 @@ static void swap_samplerates_on_filter(AVFilterContext *filter) continue; for (j = 0; j < outlink->in_samplerates->nb_formats; j++) { - int diff = abs(sample_rate - outlink->in_samplerates->formats[j]); + int diff; + switch(filter->osr_fallback_method) { + case AVOSRFB_CLOSEST: + diff = abs(sample_rate - outlink->in_samplerates->formats[j]); + break; + case AVOSRFB_HIGHER: + if ((diff = outlink->in_samplerates->formats[j] - sample_rate) >= 0) + break; + diff = INT_MAX - outlink->in_samplerates->formats[j]; + break; + case AVOSRFB_TWICE_HIGHER: + if ((diff = outlink->in_samplerates->formats[j] - sample_rate) == 0) + break; + if ((diff = outlink->in_samplerates->formats[j] - sample_rate * 2) >= 0) + break; + diff = INT_MAX - outlink->in_samplerates->formats[j]; + break; + case AVOSRFB_HIGHEST: + if ((diff = outlink->in_samplerates->formats[j] - sample_rate) == 0) + break; + diff = INT_MAX - outlink->in_samplerates->formats[j]; + break; + default: + av_assert0(0); // enum out of range + break; + } av_assert0(diff < INT_MAX); // This would lead to the use of uninitialized best_diff but is only possible with invalid sample rates _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel