@@ -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 },
};
@@ -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.
@@ -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