[FFmpeg-devel] [PATCH] swr: handle initial negative sample index outside DSP function.

Ronald S. Bultje rsbultje at gmail.com
Thu Jun 12 03:33:43 CEST 2014


The new function in struct Resampler and code therefore in resample()
are admittedly butt-ugly. I'll probably clean it up but at least it
works so I figured I'd send it out and see what people think. What I'd
really like to do is to be able to expose ResampleContext to swresample.c
if people are OK with that.
---
 libswresample/resample.c            | 47 ++++++++++++++++++++++++++++++-
 libswresample/resample_template.c   | 55 ++++---------------------------------
 libswresample/soxr_resample.c       |  7 +++++
 libswresample/swresample.c          |  6 ++++
 libswresample/swresample_internal.h |  2 ++
 5 files changed, 66 insertions(+), 51 deletions(-)

diff --git a/libswresample/resample.c b/libswresample/resample.c
index 6d30920..0499632 100644
--- a/libswresample/resample.c
+++ b/libswresample/resample.c
@@ -335,7 +335,7 @@ static int multiple_resample(ResampleContext *c, AudioData *dst, int dst_size, A
     int i, ret= -1;
     int av_unused mm_flags = av_get_cpu_flags();
     int need_emms= 0;
-    int max_src_size = (INT64_MAX >> (c->phase_shift+1)) / c->src_incr;
+    int64_t max_src_size = (INT64_MAX >> (c->phase_shift+1)) / c->src_incr;
 
     if (c->compensation_distance)
         dst_size = FFMIN(dst_size, c->compensation_distance);
@@ -407,6 +407,50 @@ static int resample_flush(struct SwrContext *s) {
     return 0;
 }
 
+// in fact the whole handle multiple ridiculously small buffers might need more thinking...
+static int invert_initial_buffer(ResampleContext *c, AudioData *dst, const AudioData *src,
+                                 int in_count, int *out_idx, int *out_sz)
+{
+    int n, ch, num = FFMIN(in_count + *out_idx, c->filter_length + 1), res;
+
+    if (c->index >= 0)
+        return 0;
+
+    if ((res = swri_realloc_audio(dst, c->filter_length * 2 + 1)) < 0)
+        return res;
+
+    // copy
+    for (n = *out_idx; n < num; n++) {
+        for (ch = 0; ch < src->ch_count; ch++) {
+            memcpy(dst->ch[ch] + ((c->filter_length + n) * c->felem_size),
+                   src->ch[ch] + ((n - *out_idx) * c->felem_size), c->felem_size);
+        }
+    }
+
+    // if not enough data is in, return and wait for more
+    if (num < c->filter_length + 1) {
+        *out_idx = num;
+        return INT_MAX;
+    }
+
+    // else invert
+    for (n = 1; n <= c->filter_length; n++) {
+        for (ch = 0; ch < src->ch_count; ch++) {
+            memcpy(dst->ch[ch] + ((c->filter_length - n) * c->felem_size),
+                   dst->ch[ch] + ((c->filter_length + n) * c->felem_size),
+                   c->felem_size);
+        }
+    }
+
+    res = num - *out_idx;
+    *out_idx = c->filter_length + (c->index >> c->phase_shift);
+    *out_sz = 1 + c->filter_length * 2 - *out_idx;
+    c->index &= c->phase_mask;
+    assert(res > 0);
+
+    return res;
+}
+
 struct Resampler const swri_resampler={
   resample_init,
   resample_free,
@@ -414,4 +458,5 @@ struct Resampler const swri_resampler={
   resample_flush,
   set_compensation,
   get_delay,
+  invert_initial_buffer,
 };
diff --git a/libswresample/resample_template.c b/libswresample/resample_template.c
index 73a672a..3063c94 100644
--- a/libswresample/resample_template.c
+++ b/libswresample/resample_template.c
@@ -107,7 +107,10 @@
 #endif
 
 int RENAME(swri_resample)(ResampleContext *c, DELEM *dst, const DELEM *src, int *consumed, int src_size, int dst_size, int update_ctx){
-    int dst_index, i;
+    int dst_index;
+#if !defined(COMMON_CORE) || !defined(LINEAR_CORE)
+    int i;
+#endif
     int index= c->index;
     int frac= c->frac;
     int dst_incr_frac= c->dst_incr % c->src_incr;
@@ -133,7 +136,7 @@ int RENAME(swri_resample)(ResampleContext *c, DELEM *dst, const DELEM *src, int
         av_assert2(index >= 0);
         *consumed= index;
         index = 0;
-    } else if (index >= 0) {
+    } else {
         int64_t end_index = (1LL + src_size - c->filter_length) << c->phase_shift;
         int64_t delta_frac = (end_index - index) * c->src_incr - c->frac;
         int delta_n = (delta_frac + c->dst_incr - 1) / c->dst_incr;
@@ -195,54 +198,6 @@ int RENAME(swri_resample)(ResampleContext *c, DELEM *dst, const DELEM *src, int
         }
 
         *consumed = sample_index;
-    } else {
-        int sample_index = 0;
-        for(dst_index=0; dst_index < dst_size; dst_index++){
-            FELEM *filter;
-            FELEM2 val=0;
-
-            sample_index += index >> c->phase_shift;
-            index &= c->phase_mask;
-            filter = ((FELEM*)c->filter_bank) + c->filter_alloc*index;
-
-            if(sample_index + c->filter_length > src_size || -sample_index >= src_size){
-                break;
-            }else if(sample_index < 0){
-                for(i=0; i<c->filter_length; i++)
-                    val += src[FFABS(sample_index + i)] * (FELEM2)filter[i];
-                OUT(dst[dst_index], val);
-            }else if(c->linear){
-                FELEM2 v2=0;
-#ifdef LINEAR_CORE
-                LINEAR_CORE
-#else
-                for(i=0; i<c->filter_length; i++){
-                    val += src[sample_index + i] * (FELEM2)filter[i];
-                    v2  += src[sample_index + i] * (FELEM2)filter[i + c->filter_alloc];
-                }
-#endif
-                val+=(v2-val)*(FELEML)frac / c->src_incr;
-                OUT(dst[dst_index], val);
-            }else{
-#ifdef COMMON_CORE
-                COMMON_CORE
-#else
-                for(i=0; i<c->filter_length; i++){
-                    val += src[sample_index + i] * (FELEM2)filter[i];
-                }
-                OUT(dst[dst_index], val);
-#endif
-            }
-
-            frac += dst_incr_frac;
-            index += dst_incr;
-            if(frac >= c->src_incr){
-                frac -= c->src_incr;
-                index++;
-            }
-        }
-        *consumed= FFMAX(sample_index, 0);
-        index += FFMIN(sample_index, 0) << c->phase_shift;
     }
 
     if(update_ctx){
diff --git a/libswresample/soxr_resample.c b/libswresample/soxr_resample.c
index 4c000db..064451d 100644
--- a/libswresample/soxr_resample.c
+++ b/libswresample/soxr_resample.c
@@ -87,7 +87,14 @@ static int64_t get_delay(struct SwrContext *s, int64_t base){
     return (int64_t)(delay_s * base + .5);
 }
 
+static int invert_initial_buffer(struct ResampleContext *c, AudioData *dst, const AudioData *src,
+                                 int in_count, int *out_idx, int *out_sz)
+{
+    return 0;
+}
+
 struct Resampler const soxr_resampler={
     create, destroy, process, flush, NULL /* set_compensation */, get_delay,
+    invert_initial_buffer,
 };
 
diff --git a/libswresample/swresample.c b/libswresample/swresample.c
index 7076650..2d063cd 100644
--- a/libswresample/swresample.c
+++ b/libswresample/swresample.c
@@ -541,6 +541,12 @@ static int resample(SwrContext *s, AudioData *out_param, int out_count,
     tmp=out=*out_param;
     in =  *in_param;
 
+    border = s->resampler->invert_initial_buffer(s->resample, &s->in_buffer,
+                 &in, in_count, &s->in_buffer_index, &s->in_buffer_count);
+    if (border == INT_MAX) return 0;
+    else if (border < 0) return border;
+    else if (border) { buf_set(&in, &in, border); in_count -= border; s->resample_in_constraint = 0; }
+
     do{
         int ret, size, consumed;
         if(!s->resample_in_constraint && s->in_buffer_count){
diff --git a/libswresample/swresample_internal.h b/libswresample/swresample_internal.h
index ab19f21..407bbac 100644
--- a/libswresample/swresample_internal.h
+++ b/libswresample/swresample_internal.h
@@ -157,6 +157,7 @@ typedef int     (* multiple_resample_func)(struct ResampleContext *c, AudioData
 typedef int     (* resample_flush_func)(struct SwrContext *c);
 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);
+typedef int     (* invert_initial_buffer_func)(struct ResampleContext *c, AudioData *dst, const AudioData *src, int src_size, int *dst_idx, int *dst_count);
 
 struct Resampler {
   resample_init_func            init;
@@ -165,6 +166,7 @@ struct Resampler {
   resample_flush_func           flush;
   set_compensation_func         set_compensation;
   get_delay_func                get_delay;
+  invert_initial_buffer_func    invert_initial_buffer;
 };
 
 extern struct Resampler const swri_resampler;
-- 
1.8.5.5



More information about the ffmpeg-devel mailing list