diff options
author | wm4 <wm4@nowhere> | 2012-12-21 18:13:16 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2012-12-28 13:43:55 +0100 |
commit | 97ed31fd8ed7241dade2e579488146e8fa3473f7 (patch) | |
tree | 2e2739caccdce9beaf29f85546e116d671961133 | |
parent | b32f2ef0d344e224a24ed72bf7abf394675ea58f (diff) | |
download | mpv-97ed31fd8ed7241dade2e579488146e8fa3473f7.tar.bz2 mpv-97ed31fd8ed7241dade2e579488146e8fa3473f7.tar.xz |
audio: make de-planarization faster
Uses the same trick as the planarization code to turn per-sample memcpy
calls into mov instructions. Makes decoding a ~25min 48000Hz 2ch floatle
audio file faster from 3.8s to 2.7s.
-rw-r--r-- | audio/decode/ad_lavc.c | 17 | ||||
-rw-r--r-- | audio/reorder_ch.c | 37 | ||||
-rw-r--r-- | audio/reorder_ch.h | 6 |
3 files changed, 44 insertions, 16 deletions
diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index e0e39e1e7d..9bcbde33cf 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -52,8 +52,8 @@ LIBAD_EXTERN(ffmpeg) struct priv { AVCodecContext *avctx; AVFrame *avframe; - char *output; - char *output_packed; // used by deplanarize to store packed audio samples + uint8_t *output; + uint8_t *output_packed; // used by deplanarize to store packed audio samples int output_left; int unitsize; int previous_data_left; // input demuxer packet data @@ -363,6 +363,7 @@ static av_always_inline void deplanarize(struct sh_audio *sh) { struct priv *priv = sh->context; + uint8_t **planes = priv->avframe->extended_data; size_t bps = av_get_bytes_per_sample(priv->avctx->sample_fmt); size_t nb_samples = priv->avframe->nb_samples; size_t channels = priv->avctx->channels; @@ -372,17 +373,7 @@ static av_always_inline void deplanarize(struct sh_audio *sh) priv->output_packed = talloc_realloc_size(priv, priv->output_packed, size); - size_t offset = 0; - unsigned char *output_ptr = priv->output_packed; - unsigned char **src = priv->avframe->data; - - for (size_t s = 0; s < nb_samples; s++) { - for (size_t c = 0; c < channels; c++) { - memcpy(output_ptr, src[c] + offset, bps); - output_ptr += bps; - } - offset += bps; - } + reorder_to_packed(priv->output_packed, planes, bps, channels, nb_samples); priv->output = priv->output_packed; } diff --git a/audio/reorder_ch.c b/audio/reorder_ch.c index 330a807eae..72849c3d13 100644 --- a/audio/reorder_ch.c +++ b/audio/reorder_ch.c @@ -1399,7 +1399,8 @@ int main(int argc, char *argv[]) { #endif static inline void reorder_to_planar_(void *restrict out, const void *restrict in, - size_t size, size_t nchan, size_t nmemb) { + size_t size, size_t nchan, size_t nmemb) +{ size_t i, c; char *outptr = (char *) out; size_t instep = nchan * size; @@ -1413,7 +1414,7 @@ static inline void reorder_to_planar_(void *restrict out, const void *restrict i } void reorder_to_planar(void *restrict out, const void *restrict in, - size_t size, size_t nchan, size_t nmemb) + size_t size, size_t nchan, size_t nmemb) { // special case for mono (nothing to do...) if (nchan == 1) @@ -1432,3 +1433,35 @@ void reorder_to_planar(void *restrict out, const void *restrict in, else reorder_to_planar_(out, in, size, nchan, nmemb); } + +static inline void reorder_to_packed_(uint8_t *out, uint8_t **in, + size_t size, size_t nchan, size_t nmemb) +{ + size_t outstep = nchan * size; + + for (size_t c = 0; c < nchan; ++c) { + char *outptr = out + c * size; + char *inptr = in[c]; + for (size_t i = 0; i < nmemb; ++i, outptr += outstep, inptr += size) { + memcpy(outptr, inptr, size); + } + } +} + +// out = destination array of packed samples of given size, nmemb frames +// in[channel] = source array of samples for the given channel +void reorder_to_packed(uint8_t *out, uint8_t **in, + size_t size, size_t nchan, size_t nmemb) +{ + if (nchan == 1) + memcpy(out, in, size * nchan * nmemb); + // See reorder_to_planar() why this is done this way + else if (size == 1) + reorder_to_packed_(out, in, 1, nchan, nmemb); + else if (size == 2) + reorder_to_packed_(out, in, 2, nchan, nmemb); + else if (size == 4) + reorder_to_packed_(out, in, 4, nchan, nmemb); + else + reorder_to_packed_(out, in, size, nchan, nmemb); +} diff --git a/audio/reorder_ch.h b/audio/reorder_ch.h index 66354403da..07daa35a08 100644 --- a/audio/reorder_ch.h +++ b/audio/reorder_ch.h @@ -23,6 +23,8 @@ #ifndef MPLAYER_REORDER_CH_H #define MPLAYER_REORDER_CH_H +#include <inttypes.h> + // L - Left // R - Right // C - Center @@ -132,6 +134,8 @@ void reorder_channel_nch(void *buf, /// Utility function for planar audio conversions void reorder_to_planar(void *restrict out, const void *restrict in, - size_t size, size_t nchan, size_t nmemb); + size_t size, size_t nchan, size_t nmemb); +void reorder_to_packed(uint8_t *out, uint8_t **in, + size_t size, size_t nchan, size_t nmemb); #endif /* MPLAYER_REORDER_CH_H */ |