[FFmpeg-cvslog] swr: More flexible and convenient buffering

Michael Niedermayer git at videolan.org
Sun Mar 25 22:17:16 CEST 2012


ffmpeg | branch: master | Michael Niedermayer <michaelni at gmx.at> | Sun Mar 25 21:04:48 2012 +0200| [1b0fcf33b80d72d1e48287feda5cea9fdf906ee0] | committer: Michael Niedermayer

swr: More flexible and convenient buffering

Signed-off-by: Michael Niedermayer <michaelni at gmx.at>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=1b0fcf33b80d72d1e48287feda5cea9fdf906ee0
---

 libswresample/swresample.c |  142 +++++++++++++++++++++++++++++++-------------
 libswresample/swresample.h |    4 +
 2 files changed, 105 insertions(+), 41 deletions(-)

diff --git a/libswresample/swresample.c b/libswresample/swresample.c
index eb83aa2..a1dcf2a 100644
--- a/libswresample/swresample.c
+++ b/libswresample/swresample.c
@@ -240,6 +240,7 @@ av_assert0(s->out.ch_count);
     s-> in.bps= av_get_bytes_per_sample(s-> in_sample_fmt);
     s->int_bps= av_get_bytes_per_sample(s->int_sample_fmt);
     s->out.bps= av_get_bytes_per_sample(s->out_sample_fmt);
+    s->in_buffer= s->in;
 
     if(!s->resample && !s->rematrix && !s->channel_map){
         s->full_convert = swri_audio_convert_alloc(s->out_sample_fmt,
@@ -256,20 +257,26 @@ av_assert0(s->out.ch_count);
     s->postin= s->in;
     s->preout= s->out;
     s->midbuf= s->in;
-    s->in_buffer= s->in;
+
     if(s->channel_map){
         s->postin.ch_count=
-        s->midbuf.ch_count=
-        s->in_buffer.ch_count= s->used_ch_count;
+        s->midbuf.ch_count= s->used_ch_count;
+        if(s->resample)
+            s->in_buffer.ch_count= s->used_ch_count;
     }
     if(!s->resample_first){
         s->midbuf.ch_count= s->out.ch_count;
-        s->in_buffer.ch_count = s->out.ch_count;
+        if(s->resample)
+            s->in_buffer.ch_count = s->out.ch_count;
     }
 
-    s->in_buffer.bps = s->postin.bps = s->midbuf.bps = s->preout.bps =  s->int_bps;
-    s->in_buffer.planar = s->postin.planar = s->midbuf.planar = s->preout.planar =  1;
+    s->postin.bps    = s->midbuf.bps    = s->preout.bps    =  s->int_bps;
+    s->postin.planar = s->midbuf.planar = s->preout.planar =  1;
 
+    if(s->resample){
+        s->in_buffer.bps    = s->int_bps;
+        s->in_buffer.planar = 1;
+    }
 
     if(s->rematrix)
         return swri_rematrix_init(s);
@@ -421,45 +428,12 @@ static int resample(SwrContext *s, AudioData *out_param, int out_count,
     return ret_sum;
 }
 
-int swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_CH_MAX], int out_count,
-                         const uint8_t *in_arg [SWR_CH_MAX], int  in_count){
+static int swr_convert_internal(struct SwrContext *s, AudioData *out[SWR_CH_MAX], int out_count,
+                                                      AudioData *in [SWR_CH_MAX], int  in_count){
     AudioData *postin, *midbuf, *preout;
     int ret/*, in_max*/;
-    AudioData * in= &s->in;
-    AudioData *out= &s->out;
     AudioData preout_tmp, midbuf_tmp;
 
-    if(!s->resample){
-        if(in_count > out_count)
-            return -1;
-        out_count = in_count;
-    }
-
-    if(!in_arg){
-        if(s->in_buffer_count){
-            if (!s->flushed) {
-                AudioData *a= &s->in_buffer;
-                int i, j, ret;
-                if((ret=realloc_audio(a, s->in_buffer_index + 2*s->in_buffer_count)) < 0)
-                    return ret;
-                av_assert0(a->planar);
-                for(i=0; i<a->ch_count; i++){
-                    for(j=0; j<s->in_buffer_count; j++){
-                        memcpy(a->ch[i] + (s->in_buffer_index+s->in_buffer_count+j  )*a->bps,
-                            a->ch[i] + (s->in_buffer_index+s->in_buffer_count-j-1)*a->bps, a->bps);
-                    }
-                }
-                s->in_buffer_count += (s->in_buffer_count+1)/2;
-                s->resample_in_constraint = 0;
-                s->flushed = 1;
-            }
-        }else{
-            return 0;
-        }
-    }else
-        fill_audiodata(in ,  (void*)in_arg);
-    fill_audiodata(out, out_arg);
-
     if(s->full_convert){
         av_assert0(!s->resample);
         swri_audio_convert(s->full_convert, out, in, in_count);
@@ -534,3 +508,89 @@ int swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_CH_MAX], int out_coun
     return out_count;
 }
 
+int swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_CH_MAX], int out_count,
+                                const uint8_t *in_arg [SWR_CH_MAX], int  in_count){
+    AudioData * in= &s->in;
+    AudioData *out= &s->out;
+
+    if(!in_arg){
+        if(s->in_buffer_count){
+            if (s->resample && !s->flushed) {
+                AudioData *a= &s->in_buffer;
+                int i, j, ret;
+                if((ret=realloc_audio(a, s->in_buffer_index + 2*s->in_buffer_count)) < 0)
+                    return ret;
+                av_assert0(a->planar);
+                for(i=0; i<a->ch_count; i++){
+                    for(j=0; j<s->in_buffer_count; j++){
+                        memcpy(a->ch[i] + (s->in_buffer_index+s->in_buffer_count+j  )*a->bps,
+                            a->ch[i] + (s->in_buffer_index+s->in_buffer_count-j-1)*a->bps, a->bps);
+                    }
+                }
+                s->in_buffer_count += (s->in_buffer_count+1)/2;
+                s->resample_in_constraint = 0;
+                s->flushed = 1;
+            }
+        }else{
+            return 0;
+        }
+    }else
+        fill_audiodata(in ,  (void*)in_arg);
+
+    fill_audiodata(out, out_arg);
+
+    if(s->resample){
+        return swr_convert_internal(s, out, out_count, in, in_count);
+    }else{
+        AudioData tmp= *in;
+        int ret2=0;
+        int ret, size;
+        int in_buffer_count= s->in_buffer_count;
+        size = FFMIN(out_count, s->in_buffer_count);
+        if(size){
+            buf_set(&tmp, &s->in_buffer, s->in_buffer_index);
+            ret= swr_convert_internal(s, out, size, &tmp, size);
+            if(ret<0)
+                return ret;
+            ret2= ret;
+            s->in_buffer_count -= ret;
+            s->in_buffer_index += ret;
+            buf_set(out, out, ret);
+            out_count -= ret;
+            if(!s->in_buffer_count)
+                s->in_buffer_index = 0;
+        }
+
+        if(in_count){
+            size= s->in_buffer_index + s->in_buffer_count + in_count - out_count;
+
+            if(in_count > out_count) { //FIXME move after swr_convert_internal
+                if(   size > s->in_buffer.count
+                && s->in_buffer_count + in_count - out_count <= s->in_buffer_index){
+                    buf_set(&tmp, &s->in_buffer, s->in_buffer_index);
+                    copy(&s->in_buffer, &tmp, s->in_buffer_count);
+                    s->in_buffer_index=0;
+                }else
+                    if((ret=realloc_audio(&s->in_buffer, size)) < 0)
+                        return ret;
+            }
+
+            if(out_count){
+                size = FFMIN(in_count, out_count);
+                ret= swr_convert_internal(s, out, size, in, size);
+                if(ret<0)
+                    return ret;
+                buf_set(in, in, ret);
+                in_count -= ret;
+                ret2 += ret;
+            }
+            if(in_count){
+                buf_set(&tmp, &s->in_buffer, s->in_buffer_index);
+                copy(&tmp, in, in_count);
+                s->in_buffer_count += in_count;
+            }
+        }
+        return ret2;
+    }
+}
+
diff --git a/libswresample/swresample.h b/libswresample/swresample.h
index f860f7c..f912bac 100644
--- a/libswresample/swresample.h
+++ b/libswresample/swresample.h
@@ -102,6 +102,10 @@ void swr_free(struct SwrContext **s);
  * in and in_count can be set to 0 to flush the last few samples out at the
  * end.
  *
+ * If more input is provided than output space then the input will be buffered.
+ * You can avoid this buffering by providing more output space than input.
+ * Convertion will run directly without copying whenever possible.
+ *
  * @param s         allocated Swr context, with parameters set
  * @param out       output buffers, only the first one need be set in case of packed audio
  * @param out_count amount of space available for output in samples per channel



More information about the ffmpeg-cvslog mailing list