[libav-commits] adpcm_ima_ws: fix stereo decoding

Justin Ruggles git at libav.org
Tue Jan 24 20:16:36 CET 2012


Module: libav
Branch: master
Commit: 02e7dbf5adc6aa702472010c33aec9bfd904702f

Author:    Justin Ruggles <justin.ruggles at gmail.com>
Committer: Justin Ruggles <justin.ruggles at gmail.com>
Date:      Mon Jan 23 12:23:27 2012 -0500

adpcm_ima_ws: fix stereo decoding

Stereo ADPCM IMA WS is planar for VQA version 3 and 2-sample interleaved for
VQA version 2.

---

 libavcodec/adpcm.c         |   30 +++++++++++++++++++++++++++++-
 libavformat/westwood_vqa.c |    6 ++++++
 2 files changed, 35 insertions(+), 1 deletions(-)

diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index 64bea6a..bd86ab0 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 4d6397b..c2aebe5 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;



More information about the libav-commits mailing list