diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2013-01-10 18:51:30 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2013-01-10 18:51:30 +0100 |
commit | e5a736261bafb1bc5a4c51d614be63e0632b2e96 (patch) | |
tree | 5c9407a8853270b262100d85943105dfe5c6f330 /libswresample | |
parent | 2eec98125eadf47d81332014734569f7c1daeb60 (diff) | |
download | ffmpeg-e5a736261bafb1bc5a4c51d614be63e0632b2e96.tar.gz |
swr: Use a temporary buffer for dither/Noise shaping when the input is read only
This avoids copying the input
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libswresample')
-rw-r--r-- | libswresample/dither.c | 2 | ||||
-rw-r--r-- | libswresample/swresample.c | 31 | ||||
-rw-r--r-- | libswresample/swresample_internal.h | 1 |
3 files changed, 20 insertions, 14 deletions
diff --git a/libswresample/dither.c b/libswresample/dither.c index d7a5b6b558..ae56c8c3ee 100644 --- a/libswresample/dither.c +++ b/libswresample/dither.c @@ -115,7 +115,9 @@ int swri_dither_init(SwrContext *s, enum AVSampleFormat out_fmt, enum AVSampleFo s->dither.method = SWR_DITHER_TRIANGULAR_HIGHPASS; } + av_assert0(!s->preout.count); s->dither.noise = s->preout; + s->dither.temp = s->preout; if (s->dither.method > SWR_DITHER_NS) { s->dither.noise.bps = 4; s->dither.noise.fmt = AV_SAMPLE_FMT_FLTP; diff --git a/libswresample/swresample.c b/libswresample/swresample.c index 92c9951dbd..4c971dc8e0 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -218,6 +218,7 @@ av_cold void swr_free(SwrContext **ss){ free_temp(&s->preout); free_temp(&s->in_buffer); free_temp(&s->dither.noise); + free_temp(&s->dither.temp); swri_audio_convert_free(&s-> in_convert); swri_audio_convert_free(&s->out_convert); swri_audio_convert_free(&s->full_convert); @@ -239,6 +240,7 @@ av_cold int swr_init(struct SwrContext *s){ free_temp(&s->preout); free_temp(&s->in_buffer); free_temp(&s->dither.noise); + free_temp(&s->dither.temp); memset(s->in.ch, 0, sizeof(s->in.ch)); memset(s->out.ch, 0, sizeof(s->out.ch)); swri_audio_convert_free(&s-> in_convert); @@ -611,11 +613,6 @@ static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_co if(s->resample_first ? !s->rematrix : !s->resample) preout= midbuf; - if (preout == in && s->dither.method) { - av_assert1(postin == midbuf && midbuf == preout); - postin = midbuf = preout = &preout_tmp; - } - if(s->int_sample_fmt == s->out_sample_fmt && s->out.planar){ if(preout==in){ out_count= FFMIN(out_count, in_count); //TODO check at the end if this is needed or redundant @@ -645,10 +642,16 @@ static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_co } if(preout != out && out_count){ + AudioData *conv_src = preout; if(s->dither.method){ int ch; int dither_count= FFMAX(out_count, 1<<16); - av_assert0(preout != in); + + if (preout == in) { + conv_src = &s->dither.temp; + if((ret=swri_realloc_audio(&s->dither.temp, dither_count))<0) + return ret; + } if((ret=swri_realloc_audio(&s->dither.noise, dither_count))<0) return ret; @@ -667,26 +670,26 @@ static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_co if(len1) for(ch=0; ch<preout->ch_count; ch++) - s->mix_2_1_simd(preout->ch[ch], preout->ch[ch], s->dither.noise.ch[ch] + s->dither.noise.bps * s->dither.noise_pos, s->native_one, 0, 0, len1); + s->mix_2_1_simd(conv_src->ch[ch], preout->ch[ch], s->dither.noise.ch[ch] + s->dither.noise.bps * s->dither.noise_pos, s->native_one, 0, 0, len1); if(out_count != len1) for(ch=0; ch<preout->ch_count; ch++) - s->mix_2_1_f(preout->ch[ch] + off, preout->ch[ch] + off, s->dither.noise.ch[ch] + s->dither.noise.bps * s->dither.noise_pos + off + len1, s->native_one, 0, 0, out_count - len1); + s->mix_2_1_f(conv_src->ch[ch] + off, preout->ch[ch] + off, s->dither.noise.ch[ch] + s->dither.noise.bps * s->dither.noise_pos + off + len1, s->native_one, 0, 0, out_count - len1); } else { for(ch=0; ch<preout->ch_count; ch++) - s->mix_2_1_f(preout->ch[ch], preout->ch[ch], s->dither.noise.ch[ch] + s->dither.noise.bps * s->dither.noise_pos, s->native_one, 0, 0, out_count); + s->mix_2_1_f(conv_src->ch[ch], preout->ch[ch], s->dither.noise.ch[ch] + s->dither.noise.bps * s->dither.noise_pos, s->native_one, 0, 0, out_count); } } else { switch(s->int_sample_fmt) { - case AV_SAMPLE_FMT_S16P :swri_noise_shaping_int16(s, preout, preout, &s->dither.noise, out_count); break; - case AV_SAMPLE_FMT_S32P :swri_noise_shaping_int32(s, preout, preout, &s->dither.noise, out_count); break; - case AV_SAMPLE_FMT_FLTP :swri_noise_shaping_float(s, preout, preout, &s->dither.noise, out_count); break; - case AV_SAMPLE_FMT_DBLP :swri_noise_shaping_double(s,preout, preout, &s->dither.noise, out_count); break; + case AV_SAMPLE_FMT_S16P :swri_noise_shaping_int16(s, conv_src, preout, &s->dither.noise, out_count); break; + case AV_SAMPLE_FMT_S32P :swri_noise_shaping_int32(s, conv_src, preout, &s->dither.noise, out_count); break; + case AV_SAMPLE_FMT_FLTP :swri_noise_shaping_float(s, conv_src, preout, &s->dither.noise, out_count); break; + case AV_SAMPLE_FMT_DBLP :swri_noise_shaping_double(s,conv_src, preout, &s->dither.noise, out_count); break; } } s->dither.noise_pos += out_count; } //FIXME packed doesnt need more than 1 chan here! - swri_audio_convert(s->out_convert, out, preout, out_count); + swri_audio_convert(s->out_convert, out, conv_src, out_count); } return out_count; } diff --git a/libswresample/swresample_internal.h b/libswresample/swresample_internal.h index 1da8d227b3..5046c6bf4c 100644 --- a/libswresample/swresample_internal.h +++ b/libswresample/swresample_internal.h @@ -62,6 +62,7 @@ struct DitherContext { float ns_coeffs[NS_TAPS]; ///< Noise shaping filter coefficients float ns_errors[SWR_CH_MAX][2*NS_TAPS]; AudioData noise; ///< noise used for dithering + AudioData temp; ///< temporary storage when writing into the input buffer isnt possible }; struct SwrContext { |