diff options
author | Baptiste Coudurier <baptiste.coudurier@gmail.com> | 2011-05-08 13:13:17 +0200 |
---|---|---|
committer | Justin Ruggles <justin.ruggles@gmail.com> | 2011-09-23 20:54:28 -0400 |
commit | bf334535b4d41e7278bd5361492cfe357b8b9821 (patch) | |
tree | f82244f3d7b712fb286a8bc76c43500b2956ea88 | |
parent | 3a549eb82be709d633a0ba964b037ee2f700e0c9 (diff) | |
download | ffmpeg-bf334535b4d41e7278bd5361492cfe357b8b9821.tar.gz |
adpcmdec: Fix QT IMA ADPCM decoder
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | libavcodec/adpcm.c | 62 | ||||
-rw-r--r-- | tests/ref/acodec/adpcm_ima_qt | 6 | ||||
-rw-r--r-- | tests/ref/fate/qt-ima4-mono | 2 | ||||
-rw-r--r-- | 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 de4fe9b11f..3baa07b982 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -150,6 +150,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 = ff_adpcm_step_table[c->step_index]; + step_index = c->step_index + ff_adpcm_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; @@ -352,35 +378,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 = ff_adpcm_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 6e4415660e..a91cd2da3d 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 66767d5d30..b8fc5f99de 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 5e6b1237d5..84c9f46d02 100644 --- a/tests/ref/fate/qt-ima4-stereo +++ b/tests/ref/fate/qt-ima4-stereo @@ -1 +1 @@ -c9e4c21fb62eca34a533f3a9ad2e394a +d22be0e193dcbba1068a1ca6ab04cf77 |