From 5846ba0a6df69e41783ab4caa88d392abd339ed1 Mon Sep 17 00:00:00 2001
From: Muhammad Faiz <mfcc64@gmail.com>
Date: Mon, 21 Nov 2016 02:08:40 +0700
Subject: [PATCH] swresample/resample: add soft_compensation argument

this allow to use larger phase_count on init (rather than
rebuild on swr_set_compensation) when options suggest that
soft compensation is enabled

this affects only when exact_rational is enabled

Signed-off-by: Muhammad Faiz <mfcc64@gmail.com>
---
 libswresample/resample.c            | 7 ++++++-
 libswresample/soxr_resample.c       | 3 ++-
 libswresample/swresample.c          | 7 ++++++-
 libswresample/swresample_internal.h | 3 ++-
 4 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/libswresample/resample.c b/libswresample/resample.c
index 8635bf1..d1822e2 100644
--- a/libswresample/resample.c
+++ b/libswresample/resample.c
@@ -302,7 +302,7 @@ fail:
 
 static ResampleContext *resample_init(ResampleContext *c, int out_rate, int in_rate, int filter_size, int phase_shift, int linear,
                                     double cutoff0, enum AVSampleFormat format, enum SwrFilterType filter_type, double kaiser_beta,
-                                    double precision, int cheby, int exact_rational)
+                                    double precision, int cheby, int exact_rational, int soft_compensation)
 {
     double cutoff = cutoff0? cutoff0 : 0.97;
     double factor= FFMIN(out_rate * cutoff / in_rate, 1.0);
@@ -316,6 +316,10 @@ static ResampleContext *resample_init(ResampleContext *c, int out_rate, int in_r
         if (phase_count_exact <= phase_count) {
             phase_count_compensation = phase_count_exact * (phase_count / phase_count_exact);
             phase_count = phase_count_exact;
+            /* use larger phase_count when soft_compensation is true */
+            /* so rebuilding filter bank at runtime is not required */
+            if (soft_compensation)
+                phase_count = phase_count_compensation;
         }
     }
 
@@ -449,6 +453,7 @@ static int rebuild_filter_bank_with_compensation(ResampleContext *c)
 static int set_compensation(ResampleContext *c, int sample_delta, int compensation_distance){
     int ret;
 
+    /* handle users who call swr_set_compensation() manually without setting soft compensation options */
     if (compensation_distance) {
         ret = rebuild_filter_bank_with_compensation(c);
         if (ret < 0)
diff --git a/libswresample/soxr_resample.c b/libswresample/soxr_resample.c
index b9c6735..595cb64 100644
--- a/libswresample/soxr_resample.c
+++ b/libswresample/soxr_resample.c
@@ -30,7 +30,8 @@
 #include <soxr.h>
 
 static struct ResampleContext *create(struct ResampleContext *c, int out_rate, int in_rate, int filter_size, int phase_shift, int linear,
-        double cutoff, enum AVSampleFormat format, enum SwrFilterType filter_type, double kaiser_beta, double precision, int cheby, int exact_rational){
+        double cutoff, enum AVSampleFormat format, enum SwrFilterType filter_type, double kaiser_beta, double precision, int cheby,
+        int exact_rational, int soft_compensation){
     soxr_error_t error;
 
     soxr_datatype_t type =
diff --git a/libswresample/swresample.c b/libswresample/swresample.c
index 0ef4dea..8f85993 100644
--- a/libswresample/swresample.c
+++ b/libswresample/swresample.c
@@ -265,7 +265,12 @@ av_cold int swr_init(struct SwrContext *s){
     }
 
     if (s->out_sample_rate!=s->in_sample_rate || (s->flags & SWR_FLAG_RESAMPLE)){
-        s->resample = s->resampler->init(s->resample, s->out_sample_rate, s->in_sample_rate, s->filter_size, s->phase_shift, s->linear_interp, s->cutoff, s->int_sample_fmt, s->filter_type, s->kaiser_beta, s->precision, s->cheby, s->exact_rational);
+        /* suggested from swr_next_pts() */
+        /* if soft_compensation is false, swr_next_pts() will not call swr_set_compensation() */
+        int soft_compensation = s->min_compensation < FLT_MAX && s->soft_compensation_duration && s->max_soft_compensation;
+        s->resample = s->resampler->init(s->resample, s->out_sample_rate, s->in_sample_rate, s->filter_size,
+                                         s->phase_shift, s->linear_interp, s->cutoff, s->int_sample_fmt, s->filter_type,
+                                         s->kaiser_beta, s->precision, s->cheby, s->exact_rational, soft_compensation);
         if (!s->resample) {
             av_log(s, AV_LOG_ERROR, "Failed to initialize resampler\n");
             return AVERROR(ENOMEM);
diff --git a/libswresample/swresample_internal.h b/libswresample/swresample_internal.h
index f2ea5a2..8de8f1e 100644
--- a/libswresample/swresample_internal.h
+++ b/libswresample/swresample_internal.h
@@ -69,7 +69,8 @@ struct DitherContext {
 };
 
 typedef struct ResampleContext * (* resample_init_func)(struct ResampleContext *c, int out_rate, int in_rate, int filter_size, int phase_shift, int linear,
-                                    double cutoff, enum AVSampleFormat format, enum SwrFilterType filter_type, double kaiser_beta, double precision, int cheby, int exact_rational);
+                                    double cutoff, enum AVSampleFormat format, enum SwrFilterType filter_type, double kaiser_beta, double precision, int cheby,
+                                    int exact_rational, int soft_compensation);
 typedef void    (* resample_free_func)(struct ResampleContext **c);
 typedef int     (* multiple_resample_func)(struct ResampleContext *c, AudioData *dst, int dst_size, AudioData *src, int src_size, int *consumed);
 typedef int     (* resample_flush_func)(struct SwrContext *c);
-- 
2.5.0

