mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-26 19:01:44 +02:00
added support for EA ADPCM and SMJPEG IMA ADPCM
Originally committed as revision 2744 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
deb7a6cdaf
commit
7d8379f2b7
1
CREDITS
1
CREDITS
@ -12,6 +12,7 @@ Philip Gladstone
|
||||
Vladimir Gneushev
|
||||
Falk Hueffner
|
||||
Zdenek Kabelac
|
||||
Robin Kay
|
||||
Nick Kurshev
|
||||
Mike Melanson
|
||||
Michael Niedermayer
|
||||
|
@ -758,9 +758,13 @@ solutions.
|
||||
@tab used in some Sega Saturn console games
|
||||
@item Westwood Studios IMA ADPCM @tab @tab X
|
||||
@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 CRI ADX ADPCM @tab X @tab X
|
||||
@tab used in Sega Dreamcast games
|
||||
@item Electronic Arts ADPCM @tab @tab X
|
||||
@tab used in various EA titles
|
||||
@item RA144 @tab @tab X
|
||||
@tab Real 14400 bit/s codec
|
||||
@item RA288 @tab @tab X
|
||||
|
@ -25,6 +25,7 @@
|
||||
* Fringe ADPCM codecs (e.g., DK3, DK4, Westwood)
|
||||
* by Mike Melanson (melanson@pcisys.net)
|
||||
* CD-ROM XA ADPCM codec by BERO
|
||||
* EA ADPCM decoder by Robin Kay (komadori@myrealbox.com)
|
||||
*
|
||||
* Features and limitations:
|
||||
*
|
||||
@ -44,6 +45,13 @@
|
||||
|
||||
#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) \
|
||||
if (value > 32767) \
|
||||
value = 32767; \
|
||||
@ -97,6 +105,11 @@ static const int xa_adpcm_table[5][2] = {
|
||||
{ 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 */
|
||||
|
||||
typedef struct ADPCMChannelStatus {
|
||||
@ -444,6 +457,15 @@ static int adpcm_decode_frame(AVCodecContext *avctx,
|
||||
int decode_top_nibble_next = 0;
|
||||
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)
|
||||
return 0;
|
||||
|
||||
@ -715,6 +737,69 @@ static int adpcm_decode_frame(AVCodecContext *avctx,
|
||||
buf_size -= 128;
|
||||
}
|
||||
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:
|
||||
*data_size = 0;
|
||||
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_DK4, adpcm_ima_dk4);
|
||||
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_4XM, adpcm_4xm);
|
||||
ADPCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa);
|
||||
ADPCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx);
|
||||
ADPCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea);
|
||||
|
||||
#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_DK4, adpcm_ima_dk4);
|
||||
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_4XM, adpcm_4xm);
|
||||
PCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa);
|
||||
PCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx);
|
||||
PCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea);
|
||||
|
||||
#undef PCM_CODEC
|
||||
|
||||
|
@ -110,10 +110,12 @@ enum CodecID {
|
||||
CODEC_ID_ADPCM_IMA_DK3,
|
||||
CODEC_ID_ADPCM_IMA_DK4,
|
||||
CODEC_ID_ADPCM_IMA_WS,
|
||||
CODEC_ID_ADPCM_IMA_SMJPEG,
|
||||
CODEC_ID_ADPCM_MS,
|
||||
CODEC_ID_ADPCM_4XM,
|
||||
CODEC_ID_ADPCM_XA,
|
||||
CODEC_ID_ADPCM_ADX,
|
||||
CODEC_ID_ADPCM_EA,
|
||||
|
||||
/* AMR */
|
||||
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_DK4, adpcm_ima_dk4);
|
||||
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_4XM, adpcm_4xm);
|
||||
PCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa);
|
||||
PCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx);
|
||||
PCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea);
|
||||
|
||||
#undef PCM_CODEC
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user