Commit e7583962 authored by Peter Ross's avatar Peter Ross Committed by Aurelien Jacobs

EA ADPCM R1, R2 and R3 decoder

original patch by Peter Ross

Originally committed as revision 10856 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent d2bbb2f7
......@@ -266,6 +266,9 @@ OBJS-$(CONFIG_ADPCM_CT_DECODER) += adpcm.o
OBJS-$(CONFIG_ADPCM_CT_ENCODER) += adpcm.o
OBJS-$(CONFIG_ADPCM_EA_DECODER) += adpcm.o
OBJS-$(CONFIG_ADPCM_EA_ENCODER) += adpcm.o
OBJS-$(CONFIG_ADPCM_EA_R1_DECODER) += adpcm.o
OBJS-$(CONFIG_ADPCM_EA_R2_DECODER) += adpcm.o
OBJS-$(CONFIG_ADPCM_EA_R3_DECODER) += adpcm.o
OBJS-$(CONFIG_ADPCM_G726_DECODER) += g726.o
OBJS-$(CONFIG_ADPCM_G726_ENCODER) += g726.o
OBJS-$(CONFIG_ADPCM_IMA_AMV_DECODER) += adpcm.o
......
......@@ -30,6 +30,7 @@
* by Mike Melanson (melanson@pcisys.net)
* CD-ROM XA ADPCM codec by BERO
* EA ADPCM decoder by Robin Kay (komadori@myrealbox.com)
* EA ADPCM R1/R2/R3 decoder by Peter Ross (pross@xvid.org)
* THP ADPCM decoder by Marco Gerards (mgerards@xs4all.nl)
*
* Features and limitations:
......@@ -144,7 +145,7 @@ typedef struct ADPCMChannelStatus {
typedef struct ADPCMContext {
int channel; /* for stereo MOVs, decode left, then decode right, then tell it's decoded */
ADPCMChannelStatus status[2];
ADPCMChannelStatus status[6];
} ADPCMContext;
/* XXX: implement encoding */
......@@ -635,8 +636,16 @@ static int adpcm_encode_frame(AVCodecContext *avctx,
static int adpcm_decode_init(AVCodecContext * avctx)
{
ADPCMContext *c = avctx->priv_data;
unsigned int max_channels = 2;
if(avctx->channels > 2U){
switch(avctx->codec->id) {
case CODEC_ID_ADPCM_EA_R1:
case CODEC_ID_ADPCM_EA_R2:
case CODEC_ID_ADPCM_EA_R3:
max_channels = 6;
break;
}
if(avctx->channels > max_channels){
return -1;
}
......@@ -1176,6 +1185,86 @@ static int adpcm_decode_frame(AVCodecContext *avctx,
}
}
break;
case CODEC_ID_ADPCM_EA_R1:
case CODEC_ID_ADPCM_EA_R2:
case CODEC_ID_ADPCM_EA_R3: {
/* channel numbering
2chan: 0=fl, 1=fr
4chan: 0=fl, 1=rl, 2=fr, 3=rr
6chan: 0=fl, 1=c, 2=fr, 3=rl, 4=rr, 5=sub */
const int big_endian = avctx->codec->id == CODEC_ID_ADPCM_EA_R3;
int32_t previous_sample, current_sample, next_sample;
int32_t coeff1, coeff2;
uint8_t shift;
unsigned int channel;
uint16_t *samplesC;
uint8_t *srcC;
samples_in_chunk = (big_endian ? bytestream_get_be32(&src)
: bytestream_get_le32(&src)) / 28;
if (samples_in_chunk > UINT32_MAX/(28*avctx->channels) ||
28*samples_in_chunk*avctx->channels > samples_end-samples) {
src += buf_size - 4;
break;
}
for (channel=0; channel<avctx->channels; channel++) {
srcC = src + (big_endian ? bytestream_get_be32(&src)
: bytestream_get_le32(&src))
+ (avctx->channels-channel-1) * 4;
samplesC = samples + channel;
if (avctx->codec->id == CODEC_ID_ADPCM_EA_R1) {
current_sample = (int16_t)bytestream_get_le16(&srcC);
previous_sample = (int16_t)bytestream_get_le16(&srcC);
} else {
current_sample = c->status[channel].predictor;
previous_sample = c->status[channel].prev_sample;
}
for (count1=0; count1<samples_in_chunk; count1++) {
if (*srcC == 0xEE) { /* only seen in R2 and R3 */
srcC++;
current_sample = (int16_t)bytestream_get_be16(&srcC);
previous_sample = (int16_t)bytestream_get_be16(&srcC);
for (count2=0; count2<28; count2++) {
*samplesC = (int16_t)bytestream_get_be16(&srcC);
samplesC += avctx->channels;
}
} else {
coeff1 = ea_adpcm_table[ (*srcC>>4) & 0x0F ];
coeff2 = ea_adpcm_table[((*srcC>>4) & 0x0F) + 4];
shift = (*srcC++ & 0x0F) + 8;
for (count2=0; count2<28; count2++) {
if (count2 & 1)
next_sample = ((*srcC++ & 0x0F) << 28) >> shift;
else
next_sample = ((*srcC & 0xF0) << 24) >> shift;
next_sample += (current_sample * coeff1) +
(previous_sample * coeff2);
next_sample = av_clip_int16(next_sample >> 8);
previous_sample = current_sample;
current_sample = next_sample;
*samplesC = current_sample;
samplesC += avctx->channels;
}
}
}
if (avctx->codec->id != CODEC_ID_ADPCM_EA_R1) {
c->status[channel].predictor = current_sample;
c->status[channel].prev_sample = previous_sample;
}
}
src = src + buf_size - (4 + 4*avctx->channels);
samples += 28 * samples_in_chunk * avctx->channels;
break;
}
case CODEC_ID_ADPCM_IMA_AMV:
case CODEC_ID_ADPCM_IMA_SMJPEG:
c->status[0].predictor = (int16_t)bytestream_get_le16(&src);
......@@ -1451,6 +1540,9 @@ ADPCM_CODEC(CODEC_ID_ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg);
ADPCM_CODEC(CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav);
ADPCM_CODEC(CODEC_ID_ADPCM_IMA_WS, adpcm_ima_ws);
ADPCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms);
ADPCM_CODEC(CODEC_ID_ADPCM_EA_R1, adpcm_ea_r1);
ADPCM_CODEC(CODEC_ID_ADPCM_EA_R2, adpcm_ea_r2);
ADPCM_CODEC(CODEC_ID_ADPCM_EA_R3, adpcm_ea_r3);
ADPCM_CODEC(CODEC_ID_ADPCM_SBPRO_4, adpcm_sbpro_4);
ADPCM_CODEC(CODEC_ID_ADPCM_SBPRO_3, adpcm_sbpro_3);
ADPCM_CODEC(CODEC_ID_ADPCM_SBPRO_2, adpcm_sbpro_2);
......
......@@ -247,6 +247,9 @@ void avcodec_register_all(void)
REGISTER_ENCDEC (ADPCM_ADX, adpcm_adx);
REGISTER_ENCDEC (ADPCM_CT, adpcm_ct);
REGISTER_ENCDEC (ADPCM_EA, adpcm_ea);
REGISTER_DECODER (ADPCM_EA_R1, adpcm_ea_r1);
REGISTER_DECODER (ADPCM_EA_R2, adpcm_ea_r2);
REGISTER_DECODER (ADPCM_EA_R3, adpcm_ea_r3);
REGISTER_ENCDEC (ADPCM_G726, adpcm_g726);
REGISTER_DECODER (ADPCM_IMA_AMV, adpcm_ima_amv);
REGISTER_ENCDEC (ADPCM_IMA_DK3, adpcm_ima_dk3);
......
......@@ -33,8 +33,8 @@
#define AV_STRINGIFY(s) AV_TOSTRING(s)
#define AV_TOSTRING(s) #s
#define LIBAVCODEC_VERSION_INT ((51<<16)+(47<<8)+0)
#define LIBAVCODEC_VERSION 51.47.0
#define LIBAVCODEC_VERSION_INT ((51<<16)+(47<<8)+1)
#define LIBAVCODEC_VERSION 51.47.1
#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT
#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION)
......@@ -211,6 +211,9 @@ enum CodecID {
CODEC_ID_ADPCM_SBPRO_2,
CODEC_ID_ADPCM_THP,
CODEC_ID_ADPCM_IMA_AMV,
CODEC_ID_ADPCM_EA_R1,
CODEC_ID_ADPCM_EA_R3,
CODEC_ID_ADPCM_EA_R2,
/* AMR */
CODEC_ID_AMR_NB= 0x12000,
......
......@@ -149,6 +149,16 @@ static int process_audio_header_elements(AVFormatContext *s)
switch (compression_type) {
case 0: ea->audio_codec = CODEC_ID_PCM_S16LE; break;
case 7: ea->audio_codec = CODEC_ID_ADPCM_EA; break;
case -1:
switch (revision) {
case 1: ea->audio_codec = CODEC_ID_ADPCM_EA_R1; break;
case 2: ea->audio_codec = CODEC_ID_ADPCM_EA_R2; break;
case 3: ea->audio_codec = CODEC_ID_ADPCM_EA_R3; break;
default:
av_log(s, AV_LOG_ERROR, "unsupported stream type; revision=%i\n", revision);
return 0;
}
break;
default:
av_log(s, AV_LOG_ERROR, "unsupported stream type; compression_type=%i\n", compression_type);
return 0;
......
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