[FFmpeg-cvslog] adpcmdec: Fix QT IMA ADPCM decoder
Baptiste Coudurier
git at videolan.org
Sun May 8 13:30:11 CEST 2011
ffmpeg | branch: master | Baptiste Coudurier <baptiste.coudurier at gmail.com> | Sun May 8 13:13:17 2011 +0200| [b3d5a4b06e344be5d5a5d64681c67c22974be937] | committer: Michael Niedermayer
adpcmdec: Fix QT IMA ADPCM decoder
Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=b3d5a4b06e344be5d5a5d64681c67c22974be937
---
libavcodec/adpcm.c | 62 +++++++++++++++++++++++++++++++----------
tests/ref/acodec/adpcm_ima_qt | 6 ++--
tests/ref/fate/qt-ima4-mono | 2 +-
tests/ref/fate/qt-ima4-stereo | 2 +-
4 files changed, 52 insertions(+), 20 deletions(-)
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index c1ceca9..e7ecead 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -808,6 +808,32 @@ static inline short adpcm_ima_expand_nibble(ADPCMChannelStatus *c, char nibble,
return (short)c->predictor;
}
+static inline int adpcm_ima_qt_expand_nibble(ADPCMChannelStatus *c, int nibble, int shift)
+{
+ int step_index;
+ int predictor;
+ int diff, step;
+
+ step = step_table[c->step_index];
+ step_index = c->step_index + index_table[nibble];
+ step_index = av_clip(step_index, 0, 88);
+
+ diff = step >> 3;
+ if (nibble & 4) diff += step;
+ if (nibble & 2) diff += step >> 1;
+ if (nibble & 1) diff += step >> 2;
+
+ if (nibble & 8)
+ predictor = c->predictor - diff;
+ else
+ predictor = c->predictor + diff;
+
+ c->predictor = av_clip_int16(predictor);
+ c->step_index = step_index;
+
+ return c->predictor;
+}
+
static inline short adpcm_ms_expand_nibble(ADPCMChannelStatus *c, char nibble)
{
int predictor;
@@ -1010,35 +1036,41 @@ static int adpcm_decode_frame(AVCodecContext *avctx,
case CODEC_ID_ADPCM_IMA_QT:
n = buf_size - 2*avctx->channels;
for (channel = 0; channel < avctx->channels; channel++) {
+ int16_t predictor;
+ int step_index;
cs = &(c->status[channel]);
/* (pppppp) (piiiiiii) */
/* Bits 15-7 are the _top_ 9 bits of the 16-bit initial predictor value */
- cs->predictor = (*src++) << 8;
- cs->predictor |= (*src & 0x80);
- cs->predictor &= 0xFF80;
-
- /* sign extension */
- if(cs->predictor & 0x8000)
- cs->predictor -= 0x10000;
-
- cs->predictor = av_clip_int16(cs->predictor);
-
- cs->step_index = (*src++) & 0x7F;
+ predictor = AV_RB16(src);
+ step_index = predictor & 0x7F;
+ predictor &= 0xFF80;
+
+ src += 2;
+
+ if (cs->step_index == step_index) {
+ int diff = (int)predictor - cs->predictor;
+ if (diff < 0)
+ diff = - diff;
+ if (diff > 0x7f)
+ goto update;
+ } else {
+ update:
+ cs->step_index = step_index;
+ cs->predictor = predictor;
+ }
if (cs->step_index > 88){
av_log(avctx, AV_LOG_ERROR, "ERROR: step_index = %i\n", cs->step_index);
cs->step_index = 88;
}
- cs->step = step_table[cs->step_index];
-
samples = (short*)data + channel;
for(m=32; n>0 && m>0; n--, m--) { /* in QuickTime, IMA is encoded by chuncks of 34 bytes (=64 samples) */
- *samples = adpcm_ima_expand_nibble(cs, src[0] & 0x0F, 3);
+ *samples = adpcm_ima_qt_expand_nibble(cs, src[0] & 0x0F, 3);
samples += avctx->channels;
- *samples = adpcm_ima_expand_nibble(cs, src[0] >> 4 , 3);
+ *samples = adpcm_ima_qt_expand_nibble(cs, src[0] >> 4 , 3);
samples += avctx->channels;
src ++;
}
diff --git a/tests/ref/acodec/adpcm_ima_qt b/tests/ref/acodec/adpcm_ima_qt
index 6e44156..a91cd2d 100644
--- a/tests/ref/acodec/adpcm_ima_qt
+++ b/tests/ref/acodec/adpcm_ima_qt
@@ -1,4 +1,4 @@
-3c06fd2f7831e3e8735b936e23ca220c *./tests/data/acodec/adpcm_qt.aiff
+019564da45949d0b5278bd75ee9a4ac2 *./tests/data/acodec/adpcm_qt.aiff
281252 ./tests/data/acodec/adpcm_qt.aiff
-9580492803ba1c1a3746367b24b751c8 *./tests/data/adpcm_ima_qt.acodec.out.wav
-stddev: 914.65 PSNR: 37.10 MAXDIFF:34026 bytes: 1058560/ 1058400
+a7fb054f7bd82270c8fd476eb9f5677c *./tests/data/adpcm_ima_qt.acodec.out.wav
+stddev: 920.19 PSNR: 37.05 MAXDIFF:34029 bytes: 1058560/ 1058400
diff --git a/tests/ref/fate/qt-ima4-mono b/tests/ref/fate/qt-ima4-mono
index 66767d5..b8fc5f9 100644
--- a/tests/ref/fate/qt-ima4-mono
+++ b/tests/ref/fate/qt-ima4-mono
@@ -1 +1 @@
-721b51fd66c3bb3dc49dd88d404188eb
+e178ed520edf2f46492ae740d88f5815
diff --git a/tests/ref/fate/qt-ima4-stereo b/tests/ref/fate/qt-ima4-stereo
index 5e6b123..84c9f46 100644
--- a/tests/ref/fate/qt-ima4-stereo
+++ b/tests/ref/fate/qt-ima4-stereo
@@ -1 +1 @@
-c9e4c21fb62eca34a533f3a9ad2e394a
+d22be0e193dcbba1068a1ca6ab04cf77
More information about the ffmpeg-cvslog
mailing list