From 53a71e1ba4b2d7ebf9c6015fd77560cc1cde8137 Mon Sep 17 00:00:00 2001 From: Robert Swain Date: Fri, 2 Oct 2009 12:59:37 +0000 Subject: [PATCH] Add vorbis channel layout support according to those defined in the Vorbis I specification Originally committed as revision 20148 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/vorbis.h | 2 ++ libavcodec/vorbis_data.c | 19 +++++++++++++++++++ libavcodec/vorbis_dec.c | 13 +++++++++++++ 3 files changed, 34 insertions(+) diff --git a/libavcodec/vorbis.h b/libavcodec/vorbis.h index 64a0b0adda..cd4dc55974 100644 --- a/libavcodec/vorbis.h +++ b/libavcodec/vorbis.h @@ -25,6 +25,8 @@ extern const float ff_vorbis_floor1_inverse_db_table[256]; extern const float * const ff_vorbis_vwin[8]; +extern const uint8_t ff_vorbis_channel_layout_offsets[6][6]; +extern const int64_t ff_vorbis_channel_layouts[7]; typedef struct { uint_fast16_t x; diff --git a/libavcodec/vorbis_data.c b/libavcodec/vorbis_data.c index 5e7a738de7..35672fa124 100644 --- a/libavcodec/vorbis_data.c +++ b/libavcodec/vorbis_data.c @@ -21,6 +21,25 @@ #include "dsputil.h" #include "vorbis.h" +const uint8_t ff_vorbis_channel_layout_offsets[6][6] = { + { 0, }, + { 0, 1, }, + { 0, 2, 1, }, + { 0, 1, 2, 3, }, + { 0, 2, 1, 3, 4, }, + { 0, 2, 1, 5, 3, 4, } +}; + +const int64_t ff_vorbis_channel_layouts[7] = { + CH_LAYOUT_MONO, + CH_LAYOUT_STEREO, + CH_LAYOUT_SURROUND, + CH_LAYOUT_QUAD, + CH_LAYOUT_5POINT0_BACK, + CH_LAYOUT_5POINT1_BACK, + 0 +}; + DECLARE_ALIGNED_16(static const float, vwin64[32]) = { 0.0009460463F, 0.0085006468F, 0.0235352254F, 0.0458950567F, 0.0753351908F, 0.1115073077F, 0.1539457973F, 0.2020557475F, diff --git a/libavcodec/vorbis_dec.c b/libavcodec/vorbis_dec.c index f9dd08833f..3dbd4b9c61 100644 --- a/libavcodec/vorbis_dec.c +++ b/libavcodec/vorbis_dec.c @@ -1012,6 +1012,11 @@ static av_cold int vorbis_decode_init(AVCodecContext *avccontext) return -1; } + if (vc->audio_channels > 6) + avccontext->channel_layout = 0; + else + avccontext->channel_layout = ff_vorbis_channel_layouts[vc->audio_channels - 1]; + avccontext->channels = vc->audio_channels; avccontext->sample_rate = vc->audio_samplerate; avccontext->frame_size = FFMIN(vc->blocksize[0], vc->blocksize[1]) >> 2; @@ -1643,8 +1648,15 @@ static int vorbis_decode_frame(AVCodecContext *avccontext, AV_DEBUG("parsed %d bytes %d bits, returned %d samples (*ch*bits) \n", get_bits_count(gb)/8, get_bits_count(gb)%8, len); + if (vc->audio_channels > 6) { for (i = 0; i < vc->audio_channels; i++) channel_ptrs[i] = vc->channel_floors + i * len; + } else { + for (i = 0; i < vc->audio_channels; i++) + channel_ptrs[i] = vc->channel_floors + + len * ff_vorbis_channel_layout_offsets[vc->audio_channels - 1][i]; + } + vc->dsp.float_to_int16_interleave(data, channel_ptrs, len, vc->audio_channels); *data_size = len * 2 * vc->audio_channels; @@ -1672,5 +1684,6 @@ AVCodec vorbis_decoder = { vorbis_decode_close, vorbis_decode_frame, .long_name = NULL_IF_CONFIG_SMALL("Vorbis"), + .channel_layouts = ff_vorbis_channel_layouts, };