diff options
author | Andrew D'Addesio <modchipv12@gmail.com> | 2012-07-09 16:29:49 -0400 |
---|---|---|
committer | Justin Ruggles <justin.ruggles@gmail.com> | 2012-07-19 13:26:48 -0400 |
commit | 1b3ef155d7033fcca4286d6e34a6c15214cb8bb0 (patch) | |
tree | c7868a1e5b79df5c5a7a27cf5154e91de77cfa05 /libavcodec/alac.c | |
parent | 81c9e2e6d074ccbf94e19c67d38b7b62e7c3f820 (diff) | |
download | ffmpeg-1b3ef155d7033fcca4286d6e34a6c15214cb8bb0.tar.gz |
alac: multi-channel decoding support
Signed-off-by: Justin Ruggles <justin.ruggles@gmail.com>
Diffstat (limited to 'libavcodec/alac.c')
-rw-r--r-- | libavcodec/alac.c | 61 |
1 files changed, 43 insertions, 18 deletions
diff --git a/libavcodec/alac.c b/libavcodec/alac.c index 1e37290740..8c8e83076f 100644 --- a/libavcodec/alac.c +++ b/libavcodec/alac.c @@ -45,7 +45,7 @@ * 32bit samplerate */ - +#include "libavutil/audioconvert.h" #include "avcodec.h" #include "get_bits.h" #include "bytestream.h" @@ -53,7 +53,7 @@ #include "mathops.h" #define ALAC_EXTRADATA_SIZE 36 -#define MAX_CHANNELS 2 +#define MAX_CHANNELS 8 typedef struct { @@ -64,9 +64,9 @@ typedef struct { int channels; /* buffers */ - int32_t *predict_error_buffer[MAX_CHANNELS]; - int32_t *output_samples_buffer[MAX_CHANNELS]; - int32_t *extra_bits_buffer[MAX_CHANNELS]; + int32_t *predict_error_buffer[2]; + int32_t *output_samples_buffer[2]; + int32_t *extra_bits_buffer[2]; uint32_t max_samples_per_frame; uint8_t sample_size; @@ -90,6 +90,28 @@ enum RawDataBlockType { TYPE_END }; +static const uint8_t alac_channel_layout_offsets[8][8] = { + { 0 }, + { 0, 1 }, + { 2, 0, 1 }, + { 2, 0, 1, 3 }, + { 2, 0, 1, 3, 4 }, + { 2, 0, 1, 4, 5, 3 }, + { 2, 0, 1, 4, 5, 6, 3 }, + { 2, 6, 7, 0, 1, 4, 5, 3 } +}; + +static const uint16_t alac_channel_layouts[8] = { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_5POINT0_BACK, + AV_CH_LAYOUT_5POINT1_BACK, + AV_CH_LAYOUT_6POINT1_BACK, + AV_CH_LAYOUT_7POINT1_WIDE_BACK +}; + static inline unsigned int decode_scalar(GetBitContext *gb, int k, int readsamplesize) { @@ -249,7 +271,7 @@ static void predictor_decompress_fir_adapt(int32_t *error_buffer, } } -static void decorrelate_stereo(int32_t *buffer[MAX_CHANNELS], +static void decorrelate_stereo(int32_t *buffer[2], int numsamples, uint8_t interlacing_shift, uint8_t interlacing_leftweight) { @@ -269,8 +291,8 @@ static void decorrelate_stereo(int32_t *buffer[MAX_CHANNELS], } } -static void append_extra_bits(int32_t *buffer[MAX_CHANNELS], - int32_t *extra_bits_buffer[MAX_CHANNELS], +static void append_extra_bits(int32_t *buffer[2], + int32_t *extra_bits_buffer[2], int extra_bits, int numchannels, int numsamples) { int i, ch; @@ -326,7 +348,7 @@ static int decode_element(AVCodecContext *avctx, void *data, int ch_index, } if (alac->sample_size > 16) { for (ch = 0; ch < channels; ch++) - alac->output_samples_buffer[ch] = (int32_t *)alac->frame.data[ch_index + ch]; + alac->output_samples_buffer[ch] = (int32_t *)alac->frame.extended_data[ch_index + ch]; } } else if (output_samples != alac->nb_samples) { av_log(avctx, AV_LOG_ERROR, "sample count mismatch: %u != %d\n", @@ -336,11 +358,11 @@ static int decode_element(AVCodecContext *avctx, void *data, int ch_index, alac->nb_samples = output_samples; if (is_compressed) { - int16_t predictor_coef_table[MAX_CHANNELS][32]; - int predictor_coef_num[MAX_CHANNELS]; - int prediction_type[MAX_CHANNELS]; - int prediction_quantitization[MAX_CHANNELS]; - int ricemodifier[MAX_CHANNELS]; + int16_t predictor_coef_table[2][32]; + int predictor_coef_num[2]; + int prediction_type[2]; + int prediction_quantitization[2]; + int ricemodifier[2]; interlacing_shift = get_bits(&alac->gb, 8); interlacing_leftweight = get_bits(&alac->gb, 8); @@ -419,7 +441,7 @@ static int decode_element(AVCodecContext *avctx, void *data, int ch_index, switch(alac->sample_size) { case 16: { for (ch = 0; ch < channels; ch++) { - int16_t *outbuffer = (int16_t *)alac->frame.data[ch_index + ch]; + int16_t *outbuffer = (int16_t *)alac->frame.extended_data[ch_index + ch]; for (i = 0; i < alac->nb_samples; i++) *outbuffer++ = alac->output_samples_buffer[ch][i]; }} @@ -462,7 +484,9 @@ static int alac_decode_frame(AVCodecContext *avctx, void *data, return AVERROR_INVALIDDATA; } - ret = decode_element(avctx, data, ch, channels); + ret = decode_element(avctx, data, + alac_channel_layout_offsets[alac->channels - 1][ch], + channels); if (ret < 0) return ret; @@ -484,7 +508,7 @@ static av_cold int alac_decode_close(AVCodecContext *avctx) ALACContext *alac = avctx->priv_data; int ch; - for (ch = 0; ch < alac->channels; ch++) { + for (ch = 0; ch < FFMIN(alac->channels, 2); ch++) { av_freep(&alac->predict_error_buffer[ch]); if (alac->sample_size == 16) av_freep(&alac->output_samples_buffer[ch]); @@ -497,7 +521,7 @@ static av_cold int alac_decode_close(AVCodecContext *avctx) static int allocate_buffers(ALACContext *alac) { int ch; - for (ch = 0; ch < alac->channels; ch++) { + for (ch = 0; ch < FFMIN(alac->channels, 2); ch++) { int buf_size = alac->max_samples_per_frame * sizeof(int32_t); FF_ALLOC_OR_GOTO(alac->avctx, alac->predict_error_buffer[ch], @@ -588,6 +612,7 @@ static av_cold int alac_decode_init(AVCodecContext * avctx) avctx->channels); return AVERROR_PATCHWELCOME; } + avctx->channel_layout = alac_channel_layouts[alac->channels - 1]; if ((ret = allocate_buffers(alac)) < 0) { av_log(avctx, AV_LOG_ERROR, "Error allocating buffers\n"); |