/* end of tables */
typedef struct ADPCMDecodeContext {
+ AVFrame frame;
ADPCMChannelStatus status[6];
+ int vqa_version; /**< VQA version. Used for ADPCM_IMA_WS */
} ADPCMDecodeContext;
static av_cold int adpcm_decode_init(AVCodecContext * avctx)
{
ADPCMDecodeContext *c = avctx->priv_data;
+ unsigned int min_channels = 1;
unsigned int max_channels = 2;
switch(avctx->codec->id) {
+ case CODEC_ID_ADPCM_EA:
+ min_channels = 2;
+ break;
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;
+ if (avctx->channels < min_channels || avctx->channels > max_channels) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n");
+ return AVERROR(EINVAL);
}
switch(avctx->codec->id) {
return -1;
}
break;
- case CODEC_ID_ADPCM_IMA_WS:
- if (avctx->extradata && avctx->extradata_size == 2 * 4) {
+ case CODEC_ID_ADPCM_IMA_APC:
+ if (avctx->extradata && avctx->extradata_size >= 8) {
c->status[0].predictor = AV_RL32(avctx->extradata);
c->status[1].predictor = AV_RL32(avctx->extradata + 4);
}
break;
+ case CODEC_ID_ADPCM_IMA_WS:
+ if (avctx->extradata && avctx->extradata_size >= 42)
+ c->vqa_version = AV_RL16(avctx->extradata);
+ break;
default:
break;
}
avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+
+ avcodec_get_frame_defaults(&c->frame);
+ avctx->coded_frame = &c->frame;
+
return 0;
}
shift = 12 - (in[4+i*2] & 15);
filter = in[4+i*2] >> 4;
+ if (filter >= FF_ARRAY_ELEMS(xa_adpcm_table)) {
+ av_log_ask_for_sample(NULL, "unknown filter %d\n", filter);
+ filter=0;
+ }
f0 = xa_adpcm_table[filter][0];
f1 = xa_adpcm_table[filter][1];
shift = 12 - (in[5+i*2] & 15);
filter = in[5+i*2] >> 4;
+ if (filter >= FF_ARRAY_ELEMS(xa_adpcm_table)) {
+ av_log_ask_for_sample(NULL, "unknown filter %d\n", filter);
+ filter=0;
+ }
f0 = xa_adpcm_table[filter][0];
f1 = xa_adpcm_table[filter][1];
*coded_samples = 0;
+ if(ch <= 0)
+ return 0;
+
switch (avctx->codec->id) {
/* constant, only check buf_size */
case CODEC_ID_ADPCM_EA_XAS:
break;
/* simple 4-bit adpcm */
case CODEC_ID_ADPCM_CT:
+ case CODEC_ID_ADPCM_IMA_APC:
case CODEC_ID_ADPCM_IMA_EA_SEAD:
case CODEC_ID_ADPCM_IMA_WS:
case CODEC_ID_ADPCM_YAMAHA:
decode_top_nibble_next = 1; \
}
-static int adpcm_decode_frame(AVCodecContext *avctx,
- void *data, int *data_size,
- AVPacket *avpkt)
+static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
+ int *got_frame_ptr, AVPacket *avpkt)
{
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
const uint8_t *src;
int st; /* stereo */
int count1, count2;
- int nb_samples, coded_samples, out_bps, out_size;
+ int nb_samples, coded_samples, ret;
nb_samples = get_nb_samples(avctx, buf, buf_size, &coded_samples);
if (nb_samples <= 0) {
return AVERROR_INVALIDDATA;
}
- out_bps = av_get_bytes_per_sample(avctx->sample_fmt);
- out_size = nb_samples * avctx->channels * out_bps;
- if (*data_size < out_size) {
- av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n");
- return AVERROR(EINVAL);
+ /* get output buffer */
+ c->frame.nb_samples = nb_samples;
+ if ((ret = avctx->get_buffer(avctx, &c->frame)) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return ret;
}
+ samples = (short *)c->frame.data[0];
+
/* use coded_samples when applicable */
/* it is always <= nb_samples, so the output buffer will be large enough */
if (coded_samples) {
if (coded_samples != nb_samples)
av_log(avctx, AV_LOG_WARNING, "mismatch in coded sample count\n");
- nb_samples = coded_samples;
- out_size = nb_samples * avctx->channels * out_bps;
+ c->frame.nb_samples = nb_samples = coded_samples;
}
- samples = data;
src = buf;
st = avctx->channels == 2 ? 1 : 0;
cs->step_index = 88;
}
- samples = (short*)data + channel;
+ samples = (short *)c->frame.data[0] + channel;
for (m = 0; m < 32; m++) {
*samples = adpcm_ima_qt_expand_nibble(cs, src[0] & 0x0F, 3);
}
for (i = 0; i < avctx->channels; i++) {
- samples = (short*)data + i;
+ samples = (short *)c->frame.data[0] + i;
cs = &c->status[i];
for (n = nb_samples >> 1; n > 0; n--, src++) {
uint8_t v = *src;
for (channel = 0; channel < avctx->channels; channel++) {
cs = &c->status[channel];
cs->predictor = (int16_t)bytestream_get_le16(&src);
- cs->step_index = *src++;
+ cs->step_index = av_clip(*src++, 0, 88);
src++;
*samples++ = cs->predictor;
}
c->status[0].predictor = (int16_t)AV_RL16(src + 10);
c->status[1].predictor = (int16_t)AV_RL16(src + 12);
- c->status[0].step_index = src[14];
- c->status[1].step_index = src[15];
+ c->status[0].step_index = av_clip(src[14], 0, 88);
+ c->status[1].step_index = av_clip(src[15], 0, 88);
/* sign extend the predictors */
src += 16;
diff_channel = c->status[1].predictor;
for (channel = 0; channel < avctx->channels; channel++) {
cs = &c->status[channel];
cs->predictor = (int16_t)bytestream_get_le16(&src);
- cs->step_index = *src++;
+ cs->step_index = av_clip(*src++, 0, 88);
src++;
}
*samples++ = adpcm_ima_expand_nibble(&c->status[st], v2, 3);
}
break;
- case CODEC_ID_ADPCM_IMA_WS:
+ case CODEC_ID_ADPCM_IMA_APC:
while (src < buf + buf_size) {
uint8_t v = *src++;
*samples++ = adpcm_ima_expand_nibble(&c->status[0], v >> 4 , 3);
*samples++ = adpcm_ima_expand_nibble(&c->status[st], v & 0x0F, 3);
}
break;
+ case CODEC_ID_ADPCM_IMA_WS:
+ for (channel = 0; channel < avctx->channels; channel++) {
+ const uint8_t *src0;
+ int src_stride;
+ int16_t *smp = samples + channel;
+
+ if (c->vqa_version == 3) {
+ src0 = src + channel * buf_size / 2;
+ src_stride = 1;
+ } else {
+ src0 = src + channel;
+ src_stride = avctx->channels;
+ }
+ for (n = nb_samples / 2; n > 0; n--) {
+ uint8_t v = *src0;
+ src0 += src_stride;
+ *smp = adpcm_ima_expand_nibble(&c->status[channel], v >> 4 , 3);
+ smp += avctx->channels;
+ *smp = adpcm_ima_expand_nibble(&c->status[channel], v & 0x0F, 3);
+ smp += avctx->channels;
+ }
+ }
+ src = buf + buf_size;
+ break;
case CODEC_ID_ADPCM_XA:
while (buf_size >= 128) {
xa_decode(samples, src, &c->status[0], &c->status[1],
src += 4; // skip sample count (already read)
for (i=0; i<=st; i++)
- c->status[i].step_index = bytestream_get_le32(&src);
+ c->status[i].step_index = av_clip(bytestream_get_le32(&src), 0, 88);
for (i=0; i<=st; i++)
c->status[i].predictor = bytestream_get_le32(&src);
/* Each EA ADPCM frame has a 12-byte header followed by 30-byte pieces,
each coding 28 stereo samples. */
+ if(avctx->channels != 2)
+ return AVERROR_INVALIDDATA;
+
src += 4; // skip sample count (already read)
current_left_sample = (int16_t)bytestream_get_le16(&src);
}
}
- out_size = count * 28 * avctx->channels * out_bps;
+ c->frame.nb_samples = count * 28;
src = src_end;
break;
}
break;
case CODEC_ID_ADPCM_IMA_AMV:
case CODEC_ID_ADPCM_IMA_SMJPEG:
- c->status[0].predictor = (int16_t)bytestream_get_le16(&src);
- c->status[0].step_index = bytestream_get_le16(&src);
-
- if (avctx->codec->id == CODEC_ID_ADPCM_IMA_AMV)
- src+=4;
+ if (avctx->codec->id == CODEC_ID_ADPCM_IMA_AMV) {
+ c->status[0].predictor = sign_extend(bytestream_get_le16(&src), 16);
+ c->status[0].step_index = av_clip(bytestream_get_le16(&src), 0, 88);
+ src += 4;
+ } else {
+ c->status[0].predictor = sign_extend(bytestream_get_be16(&src), 16);
+ c->status[0].step_index = av_clip(bytestream_get_byte(&src), 0, 88);
+ src += 1;
+ }
for (n = nb_samples >> (1 - st); n > 0; n--, src++) {
char hi, lo;
/* Initialize the previous sample. */
for (i = 0; i < 4; i++)
- prev[0][i] = (int16_t)bytestream_get_be16(&src);
+ prev[i>>1][i&1] = (int16_t)bytestream_get_be16(&src);
for (ch = 0; ch <= st; ch++) {
- samples = (unsigned short *) data + ch;
+ samples = (short *)c->frame.data[0] + ch;
/* Read in every sample for this channel. */
for (i = 0; i < nb_samples / 14; i++) {
default:
return -1;
}
- *data_size = out_size;
+
+ *got_frame_ptr = 1;
+ *(AVFrame *)data = c->frame;
+
return src - buf;
}
.priv_data_size = sizeof(ADPCMDecodeContext), \
.init = adpcm_decode_init, \
.decode = adpcm_decode_frame, \
+ .capabilities = CODEC_CAP_DR1, \
.long_name = NULL_IF_CONFIG_SMALL(long_name_), \
}
ADPCM_DECODER(CODEC_ID_ADPCM_EA_R3, adpcm_ea_r3, "ADPCM Electronic Arts R3");
ADPCM_DECODER(CODEC_ID_ADPCM_EA_XAS, adpcm_ea_xas, "ADPCM Electronic Arts XAS");
ADPCM_DECODER(CODEC_ID_ADPCM_IMA_AMV, adpcm_ima_amv, "ADPCM IMA AMV");
+ADPCM_DECODER(CODEC_ID_ADPCM_IMA_APC, adpcm_ima_apc, "ADPCM IMA CRYO APC");
ADPCM_DECODER(CODEC_ID_ADPCM_IMA_DK3, adpcm_ima_dk3, "ADPCM IMA Duck DK3");
ADPCM_DECODER(CODEC_ID_ADPCM_IMA_DK4, adpcm_ima_dk4, "ADPCM IMA Duck DK4");
ADPCM_DECODER(CODEC_ID_ADPCM_IMA_EA_EACS, adpcm_ima_ea_eacs, "ADPCM IMA Electronic Arts EACS");