[FFmpeg-devel] [PATCH] avfilter: support for output samplerate fallbacking
Takayuki 'January June' Suwa
jjsuwa.sys3175 at gmail.com
Thu Mar 9 11:34:23 EET 2017
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
More information about the ffmpeg-devel
mailing list