diff options
Diffstat (limited to 'audio/reorder_ch.c')
-rw-r--r-- | audio/reorder_ch.c | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/audio/reorder_ch.c b/audio/reorder_ch.c index 3a2b747668..57cb664a6f 100644 --- a/audio/reorder_ch.c +++ b/audio/reorder_ch.c @@ -22,8 +22,10 @@ #include <inttypes.h> #include <string.h> +#include <assert.h> -#include "audio/reorder_ch.h" +#include "chmap.h" +#include "reorder_ch.h" static inline void reorder_to_planar_(void *restrict out, const void *restrict in, size_t size, size_t nchan, size_t nmemb) @@ -92,3 +94,52 @@ void reorder_to_packed(uint8_t *out, uint8_t **in, else reorder_to_packed_(out, in, size, nchan, nmemb); } + +#define MAX_SAMPLESIZE 8 + +static void reorder_channels_(uint8_t *restrict data, int *restrict ch_order, + size_t sample_size, size_t num_ch, + size_t num_frames) +{ + char buffer[MP_NUM_CHANNELS * MAX_SAMPLESIZE]; + for (size_t f = 0; f < num_frames; f++) { + for (uint8_t c = 0; c < num_ch; c++) { + memcpy(buffer + sample_size * c, data + sample_size * ch_order[c], + sample_size); + } + memcpy(data, buffer, sample_size * num_ch); + data += num_ch * sample_size; + } +} + +// Reorders for each channel: +// out[ch] = in[ch_order[ch]] (but in-place) +// num_ch is the number of channels +// sample_size is e.g. 2 for s16le +// full byte size of in/out = num_ch * sample_size * num_frames +// Do not use this function in new code; use libavresample instead. +void reorder_channels(void *restrict data, int *restrict ch_order, + size_t sample_size, size_t num_ch, size_t num_frames) +{ + // Check 1:1 mapping + bool need_reorder = false; + for (int n = 0; n < num_ch; n++) + need_reorder |= ch_order[n] != n; + if (!need_reorder) + return; + assert(sample_size <= MAX_SAMPLESIZE); + assert(num_ch <= MP_NUM_CHANNELS); + // See reorder_to_planar() why this is done this way + // s16 and float are the most common sample sizes, and 6 channels is the + // most common case where reordering is required. + if (sample_size == 2 && num_ch == 6) + reorder_channels_(data, ch_order, 2, 6, num_frames); + else if (sample_size == 2) + reorder_channels_(data, ch_order, 2, num_ch, num_frames); + else if (sample_size == 4 && num_ch == 6) + reorder_channels_(data, ch_order, 4, 6, num_frames); + else if (sample_size == 4) + reorder_channels_(data, ch_order, 4, num_ch, num_frames); + else + reorder_channels_(data, ch_order, sample_size, num_ch, num_frames); +} |