Commit ee135a4c authored by alex's avatar alex

macromedia flavour adpcm decoding (used in flv and swf)


git-svn-id: file:///var/local/repositories/ffmpeg/trunk@3969 9553f0bf-9b14-0410-a0b8-cfaf0461ba5b
parent 97ab1ef2
......@@ -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
......@@ -241,6 +241,7 @@ PCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx);
PCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea);
PCM_CODEC(CODEC_ID_ADPCM_G726, adpcm_g726);
PCM_CODEC(CODEC_ID_ADPCM_CT, adpcm_ct);
PCM_CODEC(CODEC_ID_ADPCM_SWF, adpcm_swf);
#undef PCM_CODEC
......
......@@ -130,6 +130,7 @@ enum CodecID {
CODEC_ID_ADPCM_EA,
CODEC_ID_ADPCM_G726,
CODEC_ID_ADPCM_CT,
CODEC_ID_ADPCM_SWF,
/* AMR */
CODEC_ID_AMR_NB= 0x12000,
......@@ -2033,6 +2034,7 @@ PCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx);
PCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea);
PCM_CODEC(CODEC_ID_ADPCM_G726, adpcm_g726);
PCM_CODEC(CODEC_ID_ADPCM_CT, adpcm_ct);
PCM_CODEC(CODEC_ID_ADPCM_SWF, adpcm_swf);
#undef PCM_CODEC
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment