diff options
author | Justin Ruggles <justin.ruggles@gmail.com> | 2012-01-23 12:23:27 -0500 |
---|---|---|
committer | Justin Ruggles <justin.ruggles@gmail.com> | 2012-01-24 14:13:46 -0500 |
commit | 02e7dbf5adc6aa702472010c33aec9bfd904702f (patch) | |
tree | 652aa219661b6752ec5f15af5ed9850a7617d39d | |
parent | 220506d23f39da3e23d3d42fb7061f19cec8052c (diff) | |
download | ffmpeg-02e7dbf5adc6aa702472010c33aec9bfd904702f.tar.gz |
adpcm_ima_ws: fix stereo decoding
Stereo ADPCM IMA WS is planar for VQA version 3 and 2-sample interleaved for
VQA version 2.
-rw-r--r-- | libavcodec/adpcm.c | 30 | ||||
-rw-r--r-- | libavformat/westwood_vqa.c | 6 |
2 files changed, 35 insertions, 1 deletions
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index 64bea6a5da..bd86ab0e61 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -86,6 +86,7 @@ static const int swf_index_tables[4][16] = { typedef struct ADPCMDecodeContext { AVFrame frame; ADPCMChannelStatus status[6]; + int vqa_version; /**< VQA version. Used for ADPCM_IMA_WS */ } ADPCMDecodeContext; static av_cold int adpcm_decode_init(AVCodecContext * avctx) @@ -126,6 +127,10 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx) c->status[1].predictor = AV_RL32(avctx->extradata + 4); } break; + case CODEC_ID_ADPCM_IMA_WS: + if (avctx->extradata && avctx->extradata_size >= 42) + c->vqa_version = AV_RL16(avctx->extradata); + break; default: break; } @@ -774,7 +779,6 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, *samples++ = adpcm_ima_expand_nibble(&c->status[st], v2, 3); } break; - case CODEC_ID_ADPCM_IMA_WS: case CODEC_ID_ADPCM_IMA_APC: while (src < buf + buf_size) { uint8_t v = *src++; @@ -782,6 +786,30 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, *samples++ = adpcm_ima_expand_nibble(&c->status[st], v & 0x0F, 3); } break; + case CODEC_ID_ADPCM_IMA_WS: + for (channel = 0; channel < avctx->channels; channel++) { + const uint8_t *src0; + int src_stride; + int16_t *smp = samples + channel; + + if (c->vqa_version == 3) { + src0 = src + channel * buf_size / 2; + src_stride = 1; + } else { + src0 = src + channel; + src_stride = avctx->channels; + } + for (n = nb_samples / 2; n > 0; n--) { + uint8_t v = *src0; + src0 += src_stride; + *smp = adpcm_ima_expand_nibble(&c->status[channel], v >> 4 , 3); + smp += avctx->channels; + *smp = adpcm_ima_expand_nibble(&c->status[channel], v & 0x0F, 3); + smp += avctx->channels; + } + } + src = buf + buf_size; + break; case CODEC_ID_ADPCM_XA: while (buf_size >= 128) { xa_decode(samples, src, &c->status[0], &c->status[1], diff --git a/libavformat/westwood_vqa.c b/libavformat/westwood_vqa.c index 4d6397b88c..c2aebe5e80 100644 --- a/libavformat/westwood_vqa.c +++ b/libavformat/westwood_vqa.c @@ -128,6 +128,12 @@ static int wsvqa_read_header(AVFormatContext *s, st->start_time = 0; st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codec->extradata_size = VQA_HEADER_SIZE; + st->codec->extradata = av_mallocz(VQA_HEADER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); + if (!st->codec->extradata) + return AVERROR(ENOMEM); + memcpy(st->codec->extradata, header, VQA_HEADER_SIZE); + if (!sample_rate) sample_rate = 22050; st->codec->sample_rate = sample_rate; |