#include "get_bits.h"
#include "bytestream.h"
#include "libavutil/audioconvert.h"
+#include "libavutil/avassert.h"
/**
* @file
/** Decoder context */
typedef struct APEContext {
AVCodecContext *avctx;
+ AVFrame frame;
DSPContext dsp;
int channels;
int samples; ///< samples left to decode in current frame
uint32_t CRC; ///< frame CRC
int frameflags; ///< frame flags
- int currentframeblocks; ///< samples (per channel) in current frame
- int blocksdecoded; ///< count of decoded samples in current frame
APEPredictor predictor; ///< predictor used for final reconstruction
int32_t decoded0[BLOCKS_PER_LOOP]; ///< decoded data for the first channel
uint8_t *data; ///< current frame data
uint8_t *data_end; ///< frame data end
const uint8_t *ptr; ///< current position in frame data
- const uint8_t *last_ptr; ///< position where last 4608-sample block ended
int error;
} APEContext;
dsputil_init(&s->dsp, avctx);
avctx->sample_fmt = AV_SAMPLE_FMT_S16;
avctx->channel_layout = (avctx->channels==2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
+
+ avcodec_get_frame_defaults(&s->frame);
+ avctx->coded_frame = &s->frame;
+
return 0;
filter_alloc_fail:
ape_decode_close(avctx);
{
while (ctx->rc.range <= BOTTOM_VALUE) {
ctx->rc.buffer <<= 8;
- if(ctx->ptr < ctx->data_end)
+ if(ctx->ptr < ctx->data_end) {
ctx->rc.buffer += *ctx->ptr;
- ctx->ptr++;
+ ctx->ptr++;
+ } else {
+ ctx->error = 1;
+ }
ctx->rc.low = (ctx->rc.low << 8) | ((ctx->rc.buffer >> 1) & 0xFF);
ctx->rc.range <<= 8;
}
int32_t *decoded0 = ctx->decoded0;
int32_t *decoded1 = ctx->decoded1;
- ctx->blocksdecoded = blockstodecode;
-
if (ctx->frameflags & APE_FRAMECODE_STEREO_SILENCE) {
/* We are pure silence, just memset the output buffer. */
memset(decoded0, 0, blockstodecode * sizeof(int32_t));
*decoded1++ = ape_decode_value(ctx, &ctx->riceX);
}
}
-
- if (ctx->blocksdecoded == ctx->currentframeblocks)
- range_dec_normalize(ctx); /* normalize to use up all bytes */
}
-static void init_entropy_decoder(APEContext *ctx)
+static int init_entropy_decoder(APEContext *ctx)
{
/* Read the CRC */
+ if (ctx->data_end - ctx->ptr < 6)
+ return AVERROR_INVALIDDATA;
ctx->CRC = bytestream_get_be32(&ctx->ptr);
/* Read the frame flags if they exist */
if ((ctx->fileversion > 3820) && (ctx->CRC & 0x80000000)) {
ctx->CRC &= ~0x80000000;
+ if (ctx->data_end - ctx->ptr < 6)
+ return AVERROR_INVALIDDATA;
ctx->frameflags = bytestream_get_be32(&ctx->ptr);
}
- /* Keep a count of the blocks decoded in this frame */
- ctx->blocksdecoded = 0;
-
/* Initialize the rice structs */
ctx->riceX.k = 10;
ctx->riceX.ksum = (1 << ctx->riceX.k) * 16;
ctx->ptr++;
range_start_decoding(ctx);
+
+ return 0;
}
static const int32_t initial_coeffs[4] = {
/* Update the adaption coefficients */
absres = FFABS(res);
if (absres)
- *f->adaptcoeffs = ((res & (1<<31)) - (1<<30)) >>
+ *f->adaptcoeffs = ((res & (-1<<31)) ^ (-1<<30)) >>
(25 + (absres <= f->avg*3) + (absres <= f->avg*4/3));
else
*f->adaptcoeffs = 0;
}
}
-static void init_frame_decoder(APEContext *ctx)
+static int init_frame_decoder(APEContext *ctx)
{
- int i;
- init_entropy_decoder(ctx);
+ int i, ret;
+ if ((ret = init_entropy_decoder(ctx)) < 0)
+ return ret;
init_predictor_decoder(ctx);
for (i = 0; i < APE_FILTER_LEVELS; i++) {
init_filter(ctx, ctx->filters[i], ctx->filterbuf[i],
ape_filter_orders[ctx->fset][i]);
}
+ return 0;
}
static void ape_unpack_mono(APEContext *ctx, int count)
}
}
-static int ape_decode_frame(AVCodecContext *avctx,
- void *data, int *data_size,
- AVPacket *avpkt)
+static int ape_decode_frame(AVCodecContext *avctx, void *data,
+ int *got_frame_ptr, AVPacket *avpkt)
{
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
APEContext *s = avctx->priv_data;
- int16_t *samples = data;
- uint32_t nblocks;
- int i, n;
+ int16_t *samples;
+ int i, ret;
int blockstodecode;
- int bytes_used;
+ int bytes_used = 0;
- /* should not happen but who knows */
- if (BLOCKS_PER_LOOP * 2 * avctx->channels > *data_size) {
- av_log (avctx, AV_LOG_ERROR, "Output buffer is too small.\n");
- return AVERROR(EINVAL);
- }
+ /* this should never be negative, but bad things will happen if it is, so
+ check it just to make sure. */
+ av_assert0(s->samples >= 0);
if(!s->samples){
- void *tmp_data = av_realloc(s->data, (buf_size + 3) & ~3);
+ uint32_t nblocks, offset;
+ void *tmp_data;
+
+ if (!buf_size) {
+ *got_frame_ptr = 0;
+ return 0;
+ }
+ if (buf_size < 8) {
+ av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ tmp_data = av_realloc(s->data, FFALIGN(buf_size, 4));
if (!tmp_data)
return AVERROR(ENOMEM);
s->data = tmp_data;
s->dsp.bswap_buf((uint32_t*)s->data, (const uint32_t*)buf, buf_size >> 2);
- s->ptr = s->last_ptr = s->data;
+ s->ptr = s->data;
s->data_end = s->data + buf_size;
nblocks = bytestream_get_be32(&s->ptr);
- n = bytestream_get_be32(&s->ptr);
- if(n < 0 || n > 3){
+ offset = bytestream_get_be32(&s->ptr);
+ if (offset > 3) {
av_log(avctx, AV_LOG_ERROR, "Incorrect offset passed\n");
s->data = NULL;
return AVERROR_INVALIDDATA;
}
- s->ptr += n;
+ if (s->data_end - s->ptr < offset) {
+ av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
+ return AVERROR_INVALIDDATA;
+ }
+ s->ptr += offset;
if (!nblocks || nblocks > INT_MAX) {
av_log(avctx, AV_LOG_ERROR, "Invalid sample count: %u.\n", nblocks);
return AVERROR_INVALIDDATA;
}
- s->currentframeblocks = s->samples = nblocks;
+ s->samples = nblocks;
memset(s->decoded0, 0, sizeof(s->decoded0));
memset(s->decoded1, 0, sizeof(s->decoded1));
/* Initialize the frame decoder */
- init_frame_decoder(s);
+ if (init_frame_decoder(s) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Error reading frame header\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ bytes_used = buf_size;
}
if (!s->data) {
- *data_size = 0;
+ *got_frame_ptr = 0;
return buf_size;
}
- nblocks = s->samples;
- blockstodecode = FFMIN(BLOCKS_PER_LOOP, nblocks);
+ blockstodecode = FFMIN(BLOCKS_PER_LOOP, s->samples);
+
+ /* get output buffer */
+ s->frame.nb_samples = blockstodecode;
+ if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return ret;
+ }
+ samples = (int16_t *)s->frame.data[0];
s->error=0;
ape_unpack_stereo(s, blockstodecode);
emms_c();
- if(s->error || s->ptr > s->data_end){
+ if (s->error) {
s->samples=0;
av_log(avctx, AV_LOG_ERROR, "Error decoding frame\n");
return AVERROR_INVALIDDATA;
s->samples -= blockstodecode;
- *data_size = blockstodecode * 2 * s->channels;
- bytes_used = s->samples ? s->ptr - s->last_ptr : buf_size;
- s->last_ptr = s->ptr;
+ *got_frame_ptr = 1;
+ *(AVFrame *)data = s->frame;
+
return bytes_used;
}
.init = ape_decode_init,
.close = ape_decode_close,
.decode = ape_decode_frame,
- .capabilities = CODEC_CAP_SUBFRAMES,
+ .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DELAY | CODEC_CAP_DR1,
.flush = ape_flush,
.long_name = NULL_IF_CONFIG_SMALL("Monkey's Audio"),
};