mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
macromedia flavour adpcm decoding (used in flv and swf)
Originally committed as revision 3969 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
923bd441fe
commit
659c369256
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user