added support for EA ADPCM and SMJPEG IMA ADPCM

Originally committed as revision 2744 to svn://svn.ffmpeg.org/ffmpeg/trunk
pull/126/head
Mike Melanson 21 years ago
parent deb7a6cdaf
commit 7d8379f2b7
  1. 1
      CREDITS
  2. 4
      doc/ffmpeg-doc.texi
  3. 87
      libavcodec/adpcm.c
  4. 2
      libavcodec/allcodecs.c
  5. 4
      libavcodec/avcodec.h

@ -12,6 +12,7 @@ Philip Gladstone
Vladimir Gneushev Vladimir Gneushev
Falk Hueffner Falk Hueffner
Zdenek Kabelac Zdenek Kabelac
Robin Kay
Nick Kurshev Nick Kurshev
Mike Melanson Mike Melanson
Michael Niedermayer Michael Niedermayer

@ -758,9 +758,13 @@ solutions.
@tab used in some Sega Saturn console games @tab used in some Sega Saturn console games
@item Westwood Studios IMA ADPCM @tab @tab X @item Westwood Studios IMA ADPCM @tab @tab X
@tab used in Westwood Studios games like Command and Conquer @tab used in Westwood Studios games like Command and Conquer
@item SMJPEG IMA ADPCM @tab @tab X
@tab used in certain Loki game ports
@item CD-ROM XA ADPCM @tab @tab X @item CD-ROM XA ADPCM @tab @tab X
@item CRI ADX ADPCM @tab X @tab X @item CRI ADX ADPCM @tab X @tab X
@tab used in Sega Dreamcast games @tab used in Sega Dreamcast games
@item Electronic Arts ADPCM @tab @tab X
@tab used in various EA titles
@item RA144 @tab @tab X @item RA144 @tab @tab X
@tab Real 14400 bit/s codec @tab Real 14400 bit/s codec
@item RA288 @tab @tab X @item RA288 @tab @tab X

@ -25,6 +25,7 @@
* Fringe ADPCM codecs (e.g., DK3, DK4, Westwood) * Fringe ADPCM codecs (e.g., DK3, DK4, Westwood)
* by Mike Melanson (melanson@pcisys.net) * by Mike Melanson (melanson@pcisys.net)
* CD-ROM XA ADPCM codec by BERO * CD-ROM XA ADPCM codec by BERO
* EA ADPCM decoder by Robin Kay (komadori@myrealbox.com)
* *
* Features and limitations: * Features and limitations:
* *
@ -44,6 +45,13 @@
#define BLKSIZE 1024 #define BLKSIZE 1024
#define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
#define LE_16(x) ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
#define LE_32(x) ((((uint8_t*)(x))[3] << 24) | \
(((uint8_t*)(x))[2] << 16) | \
(((uint8_t*)(x))[1] << 8) | \
((uint8_t*)(x))[0])
#define CLAMP_TO_SHORT(value) \ #define CLAMP_TO_SHORT(value) \
if (value > 32767) \ if (value > 32767) \
value = 32767; \ value = 32767; \
@ -97,6 +105,11 @@ static const int xa_adpcm_table[5][2] = {
{ 122, -60 } { 122, -60 }
}; };
static int ea_adpcm_table[] = {
0, 240, 460, 392, 0, 0, -208, -220, 0, 1,
3, 4, 7, 8, 10, 11, 0, -1, -3, -4
};
/* end of tables */ /* end of tables */
typedef struct ADPCMChannelStatus { typedef struct ADPCMChannelStatus {
@ -444,6 +457,15 @@ static int adpcm_decode_frame(AVCodecContext *avctx,
int decode_top_nibble_next = 0; int decode_top_nibble_next = 0;
int diff_channel; int diff_channel;
/* EA ADPCM state variables */
uint32_t samples_in_chunk;
int32_t previous_left_sample, previous_right_sample;
int32_t current_left_sample, current_right_sample;
int32_t next_left_sample, next_right_sample;
int32_t coeff1l, coeff2l, coeff1r, coeff2r;
uint8_t shift_left, shift_right;
int count1, count2;
if (!buf_size) if (!buf_size)
return 0; return 0;
@ -715,6 +737,69 @@ static int adpcm_decode_frame(AVCodecContext *avctx,
buf_size -= 128; buf_size -= 128;
} }
break; break;
case CODEC_ID_ADPCM_EA:
samples_in_chunk = LE_32(src);
if (samples_in_chunk >= ((buf_size - 12) * 2)) {
src += buf_size;
break;
}
src += 4;
current_left_sample = (int16_t)LE_16(src);
src += 2;
previous_left_sample = (int16_t)LE_16(src);
src += 2;
current_right_sample = (int16_t)LE_16(src);
src += 2;
previous_right_sample = (int16_t)LE_16(src);
src += 2;
for (count1 = 0; count1 < samples_in_chunk/28;count1++) {
coeff1l = ea_adpcm_table[(*src >> 4) & 0x0F];
coeff2l = ea_adpcm_table[((*src >> 4) & 0x0F) + 4];
coeff1r = ea_adpcm_table[*src & 0x0F];
coeff2r = ea_adpcm_table[(*src & 0x0F) + 4];
src++;
shift_left = ((*src >> 4) & 0x0F) + 8;
shift_right = (*src & 0x0F) + 8;
src++;
for (count2 = 0; count2 < 28; count2++) {
next_left_sample = (((*src & 0xF0) << 24) >> shift_left);
next_right_sample = (((*src & 0x0F) << 28) >> shift_right);
src++;
next_left_sample = (next_left_sample +
(current_left_sample * coeff1l) +
(previous_left_sample * coeff2l) + 0x80) >> 8;
next_right_sample = (next_right_sample +
(current_right_sample * coeff1r) +
(previous_right_sample * coeff2r) + 0x80) >> 8;
CLAMP_TO_SHORT(next_left_sample);
CLAMP_TO_SHORT(next_right_sample);
previous_left_sample = current_left_sample;
current_left_sample = next_left_sample;
previous_right_sample = current_right_sample;
current_right_sample = next_right_sample;
*samples++ = (unsigned short)current_left_sample;
*samples++ = (unsigned short)current_right_sample;
}
}
break;
case CODEC_ID_ADPCM_IMA_SMJPEG:
c->status[0].predictor = *src;
src += 2;
c->status[0].step_index = *src++;
src++; /* skip another byte before getting to the meat */
while (src < buf + buf_size) {
*samples++ = adpcm_ima_expand_nibble(&c->status[0],
*src & 0x0F, 3);
*samples++ = adpcm_ima_expand_nibble(&c->status[0],
(*src >> 4) & 0x0F, 3);
src++;
}
break;
default: default:
*data_size = 0; *data_size = 0;
return -1; return -1;
@ -765,9 +850,11 @@ ADPCM_CODEC(CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav);
ADPCM_CODEC(CODEC_ID_ADPCM_IMA_DK3, adpcm_ima_dk3); ADPCM_CODEC(CODEC_ID_ADPCM_IMA_DK3, adpcm_ima_dk3);
ADPCM_CODEC(CODEC_ID_ADPCM_IMA_DK4, adpcm_ima_dk4); ADPCM_CODEC(CODEC_ID_ADPCM_IMA_DK4, adpcm_ima_dk4);
ADPCM_CODEC(CODEC_ID_ADPCM_IMA_WS, adpcm_ima_ws); ADPCM_CODEC(CODEC_ID_ADPCM_IMA_WS, adpcm_ima_ws);
ADPCM_CODEC(CODEC_ID_ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg);
ADPCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms); ADPCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms);
ADPCM_CODEC(CODEC_ID_ADPCM_4XM, adpcm_4xm); ADPCM_CODEC(CODEC_ID_ADPCM_4XM, adpcm_4xm);
ADPCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa); ADPCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa);
ADPCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx); ADPCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx);
ADPCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea);
#undef ADPCM_CODEC #undef ADPCM_CODEC

@ -196,10 +196,12 @@ PCM_CODEC(CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav);
PCM_CODEC(CODEC_ID_ADPCM_IMA_DK3, adpcm_ima_dk3); PCM_CODEC(CODEC_ID_ADPCM_IMA_DK3, adpcm_ima_dk3);
PCM_CODEC(CODEC_ID_ADPCM_IMA_DK4, adpcm_ima_dk4); PCM_CODEC(CODEC_ID_ADPCM_IMA_DK4, adpcm_ima_dk4);
PCM_CODEC(CODEC_ID_ADPCM_IMA_WS, adpcm_ima_ws); PCM_CODEC(CODEC_ID_ADPCM_IMA_WS, adpcm_ima_ws);
PCM_CODEC(CODEC_ID_ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg);
PCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms); PCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms);
PCM_CODEC(CODEC_ID_ADPCM_4XM, adpcm_4xm); PCM_CODEC(CODEC_ID_ADPCM_4XM, adpcm_4xm);
PCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa); PCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa);
PCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx); PCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx);
PCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea);
#undef PCM_CODEC #undef PCM_CODEC

@ -110,10 +110,12 @@ enum CodecID {
CODEC_ID_ADPCM_IMA_DK3, CODEC_ID_ADPCM_IMA_DK3,
CODEC_ID_ADPCM_IMA_DK4, CODEC_ID_ADPCM_IMA_DK4,
CODEC_ID_ADPCM_IMA_WS, CODEC_ID_ADPCM_IMA_WS,
CODEC_ID_ADPCM_IMA_SMJPEG,
CODEC_ID_ADPCM_MS, CODEC_ID_ADPCM_MS,
CODEC_ID_ADPCM_4XM, CODEC_ID_ADPCM_4XM,
CODEC_ID_ADPCM_XA, CODEC_ID_ADPCM_XA,
CODEC_ID_ADPCM_ADX, CODEC_ID_ADPCM_ADX,
CODEC_ID_ADPCM_EA,
/* AMR */ /* AMR */
CODEC_ID_AMR_NB, CODEC_ID_AMR_NB,
@ -1726,10 +1728,12 @@ PCM_CODEC(CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav);
PCM_CODEC(CODEC_ID_ADPCM_IMA_DK3, adpcm_ima_dk3); PCM_CODEC(CODEC_ID_ADPCM_IMA_DK3, adpcm_ima_dk3);
PCM_CODEC(CODEC_ID_ADPCM_IMA_DK4, adpcm_ima_dk4); PCM_CODEC(CODEC_ID_ADPCM_IMA_DK4, adpcm_ima_dk4);
PCM_CODEC(CODEC_ID_ADPCM_IMA_WS, adpcm_ima_ws); PCM_CODEC(CODEC_ID_ADPCM_IMA_WS, adpcm_ima_ws);
PCM_CODEC(CODEC_ID_ADPCM_SMJPEG, adpcm_ima_smjpeg);
PCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms); PCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms);
PCM_CODEC(CODEC_ID_ADPCM_4XM, adpcm_4xm); PCM_CODEC(CODEC_ID_ADPCM_4XM, adpcm_4xm);
PCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa); PCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa);
PCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx); PCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx);
PCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea);
#undef PCM_CODEC #undef PCM_CODEC

Loading…
Cancel
Save