[FFmpeg-devel] avfilter: support for output samplerate fallbacking

Submitted by Takayuki 'January June' Suwa on March 9, 2017, 9:34 a.m.

Details

Message ID 1489052063-24497-1-git-send-email-jjsuwa.sys3175@gmail.com
State New
Headers show

Commit Message

Takayuki 'January June' Suwa March 9, 2017, 9:34 a.m.
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(-)

Patch hide | download patch | download mbox

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