From 1b0fcf33b80d72d1e48287feda5cea9fdf906ee0 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 25 Mar 2012 21:04:48 +0200 Subject: [PATCH] swr: More flexible and convenient buffering Signed-off-by: Michael Niedermayer --- 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 eb83aa2934..a1dcf2a203 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; ich_count; i++){ - for(j=0; jin_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; ich_count; i++){ + for(j=0; jin_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 f860f7cdd6..f912bac042 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