swr: Add API to make resample engine selectable.
authorRob Sykes <aquegg@yahoo.co.uk>
Tue, 11 Dec 2012 17:36:58 +0000 (18:36 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Tue, 11 Dec 2012 21:04:00 +0000 (22:04 +0100)
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
libswresample/resample.c
libswresample/swresample.c
libswresample/swresample.h
libswresample/swresample_internal.h

index 2096e43..f3881cd 100644 (file)
@@ -195,7 +195,7 @@ static int build_filter(ResampleContext *c, void *filter, double factor, int tap
     return 0;
 }
 
-ResampleContext *swri_resample_init(ResampleContext *c, int out_rate, int in_rate, int filter_size, int phase_shift, int linear,
+static ResampleContext *resample_init(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, int kaiser_beta){
     double factor= FFMIN(out_rate * cutoff / in_rate, 1.0);
     int phase_count= 1<<phase_shift;
@@ -259,28 +259,14 @@ error:
     return NULL;
 }
 
-void swri_resample_free(ResampleContext **c){
+static void resample_free(ResampleContext **c){
     if(!*c)
         return;
     av_freep(&(*c)->filter_bank);
     av_freep(c);
 }
 
-int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance){
-    ResampleContext *c;
-    int ret;
-
-    if (!s || compensation_distance < 0)
-        return AVERROR(EINVAL);
-    if (!compensation_distance && sample_delta)
-        return AVERROR(EINVAL);
-    if (!s->resample) {
-        s->flags |= SWR_FLAG_RESAMPLE;
-        ret = swr_init(s);
-        if (ret < 0)
-            return ret;
-    }
-    c= s->resample;
+static int set_compensation(ResampleContext *c, int sample_delta, int compensation_distance){
     c->compensation_distance= compensation_distance;
     if (compensation_distance)
         c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr * (int64_t)sample_delta / compensation_distance;
@@ -322,7 +308,7 @@ int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensatio
 
 #endif // HAVE_MMXEXT_INLINE
 
-int swri_multiple_resample(ResampleContext *c, AudioData *dst, int dst_size, AudioData *src, int src_size, int *consumed){
+static int multiple_resample(ResampleContext *c, AudioData *dst, int dst_size, AudioData *src, int src_size, int *consumed){
     int i, ret= -1;
     int av_unused mm_flags = av_get_cpu_flags();
     int need_emms= 0;
@@ -348,17 +334,20 @@ int swri_multiple_resample(ResampleContext *c, AudioData *dst, int dst_size, Aud
     return ret;
 }
 
-int64_t swr_get_delay(struct SwrContext *s, int64_t base){
+static int64_t get_delay(struct SwrContext *s, int64_t base){
     ResampleContext *c = s->resample;
-    if(c){
-        int64_t num = s->in_buffer_count - (c->filter_length-1)/2;
-        num <<= c->phase_shift;
-        num -= c->index;
-        num *= c->src_incr;
-        num -= c->frac;
-
-        return av_rescale(num, base, s->in_sample_rate*(int64_t)c->src_incr << c->phase_shift);
-    }else{
-        return (s->in_buffer_count*base + (s->in_sample_rate>>1))/ s->in_sample_rate;
-    }
+    int64_t num = s->in_buffer_count - (c->filter_length-1)/2;
+    num <<= c->phase_shift;
+    num -= c->index;
+    num *= c->src_incr;
+    num -= c->frac;
+    return av_rescale(num, base, s->in_sample_rate*(int64_t)c->src_incr << c->phase_shift);
 }
+
+struct Resampler const swri_resampler={
+  resample_init,
+  resample_free,
+  multiple_resample,
+  set_compensation,
+  get_delay,
+};
index c1668da..1eaa415 100644 (file)
@@ -84,6 +84,8 @@ static const AVOption options[]={
 {"phase_shift"          , "set resampling phase shift"  , OFFSET(phase_shift)    , AV_OPT_TYPE_INT  , {.i64=10                    }, 0      , 30        , PARAM },
 {"linear_interp"        , "enable linear interpolation" , OFFSET(linear_interp)  , AV_OPT_TYPE_INT  , {.i64=0                     }, 0      , 1         , PARAM },
 {"cutoff"               , "set cutoff frequency ratio"  , OFFSET(cutoff)         , AV_OPT_TYPE_DOUBLE,{.dbl=0.8                   }, 0      , 1         , PARAM },
+{"resampler"            , "set resampling Engine"       , OFFSET(engine)         , AV_OPT_TYPE_INT  , {.i64=0                     }, 0      , SWR_ENGINE_NB-1, PARAM, "resampler"},
+{"swr"                  , "select SW Resampler"         , 0                      , AV_OPT_TYPE_CONST, {.i64=SWR_ENGINE_SWR        }, INT_MIN, INT_MAX   , PARAM, "resampler"},
 {"min_comp"             , "set minimum difference between timestamps and audio data (in seconds) below which no timestamp compensation of either kind is applied"
                                                         , OFFSET(min_compensation),AV_OPT_TYPE_FLOAT ,{.dbl=FLT_MAX               }, 0      , FLT_MAX   , PARAM },
 {"min_hard_comp"        , "set minimum difference between timestamps and audio data (in seconds) to trigger padding/trimming the data."
@@ -205,7 +207,8 @@ av_cold void swr_free(SwrContext **ss){
         swri_audio_convert_free(&s-> in_convert);
         swri_audio_convert_free(&s->out_convert);
         swri_audio_convert_free(&s->full_convert);
-        swri_resample_free(&s->resample);
+        if (s->resampler)
+            s->resampler->free(&s->resample);
         swri_rematrix_free(s);
     }
 
@@ -258,13 +261,20 @@ av_cold int swr_init(struct SwrContext *s){
         return AVERROR(EINVAL);
     }
 
+    switch(s->engine){
+        case SWR_ENGINE_SWR : s->resampler = &swri_resampler; break;
+        default:
+            av_log(s, AV_LOG_ERROR, "Requested resampling engine is unavailable\n");
+            return AVERROR(EINVAL);
+    }
+
     set_audiodata_fmt(&s-> in, s-> in_sample_fmt);
     set_audiodata_fmt(&s->out, s->out_sample_fmt);
 
     if (s->out_sample_rate!=s->in_sample_rate || (s->flags & SWR_FLAG_RESAMPLE)){
-        s->resample = swri_resample_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->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);
     }else
-        swri_resample_free(&s->resample);
+        s->resampler->free(&s->resample);
     if(    s->int_sample_fmt != AV_SAMPLE_FMT_S16P
         && s->int_sample_fmt != AV_SAMPLE_FMT_S32P
         && s->int_sample_fmt != AV_SAMPLE_FMT_FLTP
@@ -463,7 +473,7 @@ static int resample(SwrContext *s, AudioData *out_param, int out_count,
         int ret, size, consumed;
         if(!s->resample_in_constraint && s->in_buffer_count){
             buf_set(&tmp, &s->in_buffer, s->in_buffer_index);
-            ret= swri_multiple_resample(s->resample, &out, out_count, &tmp, s->in_buffer_count, &consumed);
+            ret= s->resampler->multiple_resample(s->resample, &out, out_count, &tmp, s->in_buffer_count, &consumed);
             out_count -= ret;
             ret_sum += ret;
             buf_set(&out, &out, ret);
@@ -483,7 +493,7 @@ static int resample(SwrContext *s, AudioData *out_param, int out_count,
 
         if(in_count && !s->in_buffer_count){
             s->in_buffer_index=0;
-            ret= swri_multiple_resample(s->resample, &out, out_count, &in, in_count, &consumed);
+            ret= s->resampler->multiple_resample(s->resample, &out, out_count, &in, in_count, &consumed);
             out_count -= ret;
             ret_sum += ret;
             buf_set(&out, &out, ret);
@@ -771,6 +781,34 @@ int swr_inject_silence(struct SwrContext *s, int count){
     return ret;
 }
 
+int64_t swr_get_delay(struct SwrContext *s, int64_t base){
+    if (s->resampler && s->resample){
+        return s->resampler->get_delay(s, base);
+    }else{
+        return (s->in_buffer_count*base + (s->in_sample_rate>>1))/ s->in_sample_rate;
+    }
+}
+
+int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance){
+    int ret;
+
+    if (!s || compensation_distance < 0)
+        return AVERROR(EINVAL);
+    if (!compensation_distance && sample_delta)
+        return AVERROR(EINVAL);
+    if (!s->resample) {
+        s->flags |= SWR_FLAG_RESAMPLE;
+        ret = swr_init(s);
+        if (ret < 0)
+            return ret;
+    }
+    if (!s->resampler->set_compensation){
+        return AVERROR(EINVAL);
+    }else{
+        return s->resampler->set_compensation(s->resample, sample_delta, compensation_distance);
+    }
+}
+
 int64_t swr_next_pts(struct SwrContext *s, int64_t pts){
     if(pts == INT64_MIN)
         return s->outpts;
index 8d9f77d..356fb61 100644 (file)
@@ -114,6 +114,12 @@ enum SwrDitherType {
     SWR_DITHER_NB,              ///< not part of API/ABI
 };
 
+/** Resampling Engines */
+enum SwrEngine {
+    SWR_ENGINE_SWR,             /**< SW Resampler */
+    SWR_ENGINE_NB,              ///< not part of API/ABI
+};
+
 /** Resampling Filter Types */
 enum SwrFilterType {
     SWR_FILTER_TYPE_CUBIC,              /**< Cubic */
index 459b1b0..6d607e5 100644 (file)
@@ -67,6 +67,7 @@ struct SwrContext {
     enum AVMatrixEncoding matrix_encoding;          /**< matrixed stereo encoding */
     const int *channel_map;                         ///< channel index (or -1 if muted channel) map
     int used_ch_count;                              ///< number of used input channels (mapped channel count if channel_map, otherwise in.ch_count)
+    enum SwrEngine engine;
     enum SwrDitherType dither_method;
     int dither_pos;
     float dither_scale;
@@ -104,6 +105,7 @@ struct SwrContext {
     struct AudioConvert *out_convert;               ///< output conversion context
     struct AudioConvert *full_convert;              ///< full conversion context (single conversion for input and output)
     struct ResampleContext *resample;               ///< resampling context
+    struct Resampler const *resampler;              ///< resampler virtual function table
 
     float matrix[SWR_CH_MAX][SWR_CH_MAX];           ///< floating point rematrixing coefficients
     uint8_t *native_matrix;
@@ -122,10 +124,23 @@ struct SwrContext {
     /* TODO: callbacks for ASM optimizations */
 };
 
-struct ResampleContext *swri_resample_init(struct ResampleContext *, int out_rate, int in_rate, int filter_size, int phase_shift, int linear, double cutoff, enum AVSampleFormat, enum SwrFilterType, int kaiser_beta);
-void swri_resample_free(struct ResampleContext **c);
-int swri_multiple_resample(struct ResampleContext *c, AudioData *dst, int dst_size, AudioData *src, int src_size, int *consumed);
-void swri_resample_compensate(struct ResampleContext *c, int sample_delta, int compensation_distance);
+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, int kaiser_beta);
+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     (* set_compensation_func)(struct ResampleContext *c, int sample_delta, int compensation_distance);
+typedef int64_t (* get_delay_func)(struct SwrContext *s, int64_t base);
+
+struct Resampler {
+  resample_init_func            init;
+  resample_free_func            free;
+  multiple_resample_func        multiple_resample;
+  set_compensation_func         set_compensation;
+  get_delay_func                get_delay;
+};
+
+extern struct Resampler const swri_resampler;
+
 int swri_resample_int16(struct ResampleContext *c, int16_t *dst, const int16_t *src, int *consumed, int src_size, int dst_size, int update_ctx);
 int swri_resample_int32(struct ResampleContext *c, int32_t *dst, const int32_t *src, int *consumed, int src_size, int dst_size, int update_ctx);
 int swri_resample_float(struct ResampleContext *c, float   *dst, const float   *src, int *consumed, int src_size, int dst_size, int update_ctx);