diff options
author | Alex Beregszaszi <alex@rtfs.hu> | 2005-02-21 19:27:32 +0000 |
---|---|---|
committer | Alex Beregszaszi <alex@rtfs.hu> | 2005-02-21 19:27:32 +0000 |
commit | 659c36925665462a5dec13490359702e48b56160 (patch) | |
tree | c368e77f6ef73542cfdb62c35854e1884f20c8fd /libavcodec/adpcm.c | |
parent | 923bd441fed9d87a3dd2af5f100f99b392cfaff3 (diff) | |
download | ffmpeg-streaming-659c36925665462a5dec13490359702e48b56160.zip ffmpeg-streaming-659c36925665462a5dec13490359702e48b56160.tar.gz |
macromedia flavour adpcm decoding (used in flv and swf)
Originally committed as revision 3969 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/adpcm.c')
-rw-r--r-- | libavcodec/adpcm.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index 40c2d43..043c4d4 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -17,6 +17,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "avcodec.h" +#include "bitstream.h" /** * @file adpcm.c @@ -108,6 +109,14 @@ static int ct_adpcm_table[8] = { 0x0133, 0x0199, 0x0200, 0x0266 }; +// padded to zero where table size is less then 16 +static int swf_index_tables[4][16] = { + /*2*/ { -1, 2 }, + /*3*/ { -1, -1, 2, 4 }, + /*4*/ { -1, -1, -1, -1, 2, 4, 6, 8 }, + /*5*/ { -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16 } +}; + /* end of tables */ typedef struct ADPCMChannelStatus { @@ -129,6 +138,10 @@ typedef struct ADPCMContext { int channel; /* for stereo MOVs, decode left, then decode right, then tell it's decoded */ ADPCMChannelStatus status[2]; short sample_buffer[32]; /* hold left samples while waiting for right samples */ + + /* SWF only */ + int nb_bits; + int nb_samples; } ADPCMContext; /* XXX: implement encoding */ @@ -895,6 +908,76 @@ static int adpcm_decode_frame(AVCodecContext *avctx, src++; } break; + case CODEC_ID_ADPCM_SWF: + { + GetBitContext gb; + int *table; + int k0, signmask; + int size = buf_size*8; + + init_get_bits(&gb, buf, size); + + // first frame, read bits & inital values + if (!c->nb_bits) + { + c->nb_bits = get_bits(&gb, 2)+2; +// av_log(NULL,AV_LOG_INFO,"nb_bits: %d\n", c->nb_bits); + } + + table = swf_index_tables[c->nb_bits-2]; + k0 = 1 << (c->nb_bits-2); + signmask = 1 << (c->nb_bits-1); + + while (get_bits_count(&gb) <= size) + { + int i; + + c->nb_samples++; + // wrap around at every 4096 samples... + if ((c->nb_samples & 0xfff) == 1) + { + for (i = 0; i <= st; i++) + { + *samples++ = c->status[i].predictor = get_sbits(&gb, 16); + c->status[i].step_index = get_bits(&gb, 6); + } + } + + // similar to IMA adpcm + for (i = 0; i <= st; i++) + { + int delta = get_bits(&gb, c->nb_bits); + int step = step_table[c->status[i].step_index]; + long vpdiff = 0; // vpdiff = (delta+0.5)*step/4 + int k = k0; + + do { + if (delta & k) + vpdiff += step; + step >>= 1; + k >>= 1; + } while(k); + vpdiff += step; + + if (delta & signmask) + c->status[i].predictor -= vpdiff; + else + c->status[i].predictor += vpdiff; + + c->status[i].step_index += table[delta & (~signmask)]; + + c->status[i].step_index = clip(c->status[i].step_index, 0, 88); + c->status[i].predictor = clip(c->status[i].predictor, -32768, 32767); + + *samples++ = c->status[i].predictor; + } + } + +// src += get_bits_count(&gb)*8; + src += size; + + break; + } default: return -1; } @@ -951,5 +1034,6 @@ ADPCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa); ADPCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx); ADPCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea); ADPCM_CODEC(CODEC_ID_ADPCM_CT, adpcm_ct); +ADPCM_CODEC(CODEC_ID_ADPCM_SWF, adpcm_swf); #undef ADPCM_CODEC |