aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustin Ruggles <justin.ruggles@gmail.com>2012-01-23 12:23:27 -0500
committerJustin Ruggles <justin.ruggles@gmail.com>2012-01-24 14:13:46 -0500
commit02e7dbf5adc6aa702472010c33aec9bfd904702f (patch)
tree652aa219661b6752ec5f15af5ed9850a7617d39d
parent220506d23f39da3e23d3d42fb7061f19cec8052c (diff)
downloadffmpeg-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.c30
-rw-r--r--libavformat/westwood_vqa.c6
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;