#include "libavutil/float_dsp.h"
#include "libavutil/intfloat.h"
#include "libavutil/intreadwrite.h"
+#include "libavutil/mem_internal.h"
+
#include "avcodec.h"
#include "internal.h"
#include "get_bits.h"
av_log(avctx, AV_LOG_ERROR, "invalid number of channels per XMA stream %d\n",
s->nb_channels);
return AVERROR_INVALIDDATA;
- } else if (s->nb_channels > WMAPRO_MAX_CHANNELS) {
+ } else if (s->nb_channels > WMAPRO_MAX_CHANNELS || s->nb_channels > avctx->channels) {
avpriv_request_sample(avctx,
"More than %d channels", WMAPRO_MAX_CHANNELS);
return AVERROR_PATCHWELCOME;
for (i = 0; i < WMAPRO_BLOCK_SIZES; i++)
ff_mdct_init(&s->mdct_ctx[i], WMAPRO_BLOCK_MIN_BITS+1+i, 1,
1.0 / (1 << (WMAPRO_BLOCK_MIN_BITS + i - 1))
- / (1 << (s->bits_per_sample - 1)));
+ / (1ll << (s->bits_per_sample - 1)));
/** init MDCT windows: simple sine window */
for (i = 0; i < WMAPRO_BLOCK_SIZES; i++) {
s->frame_offset = get_bits_count(gb) & 7;
s->num_saved_bits = s->frame_offset;
init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE);
- }
-
- buflen = (put_bits_count(&s->pb) + len + 8) >> 3;
+ buflen = (s->num_saved_bits + len + 7) >> 3;
+ } else
+ buflen = (put_bits_count(&s->pb) + len + 7) >> 3;
if (len <= 0 || buflen > MAX_FRAMESIZE) {
avpriv_request_sample(s->avctx, "Too small input buffer");
s->num_saved_bits += len;
if (!append) {
- avpriv_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3),
+ ff_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3),
s->num_saved_bits);
} else {
int align = 8 - (get_bits_count(gb) & 7);
align = FFMIN(align, len);
put_bits(&s->pb, align, get_bits(gb, align));
len -= align;
- avpriv_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), len);
+ ff_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), len);
}
skip_bits_long(gb, len);
if (avctx->codec_id == AV_CODEC_ID_WMAPRO && buf_size < avctx->block_align) {
av_log(avctx, AV_LOG_ERROR, "Input packet too small (%d < %d)\n",
buf_size, avctx->block_align);
+ s->packet_loss = 1;
return AVERROR_INVALIDDATA;
}
}
} else {
int frame_size;
+
+ if (avpkt->size < s->next_packet_start) {
+ s->packet_loss = 1;
+ return AVERROR_INVALIDDATA;
+ }
+
s->buf_bit_size = (avpkt->size - s->next_packet_start) << 3;
init_get_bits(gb, avpkt->data, s->buf_bit_size);
skip_bits(gb, s->packet_offset);
AVFrame *frame = data;
int i, ret, offset = INT_MAX;
+ if (!s->frames[s->current_stream]->data[0]) {
+ s->frames[s->current_stream]->nb_samples = 512;
+ if ((ret = ff_get_buffer(avctx, s->frames[s->current_stream], 0)) < 0) {
+ return ret;
+ }
+ }
/* decode current stream packet */
ret = decode_packet(avctx, &s->xma[s->current_stream], s->frames[s->current_stream],
&got_stream_frame_ptr, avpkt);
+ if (got_stream_frame_ptr && s->offset[s->current_stream] >= 64) {
+ got_stream_frame_ptr = 0;
+ ret = AVERROR_INVALIDDATA;
+ }
+
/* copy stream samples (1/2ch) to sample buffer (Nch) */
if (got_stream_frame_ptr) {
int start_ch = s->start_channel[s->current_stream];
s->num_streams = avctx->extradata[1];
if (avctx->extradata_size != (32 + ((avctx->extradata[0]==3)?0:8) + 4*s->num_streams)) {
av_log(avctx, AV_LOG_ERROR, "Incorrect XMA2 extradata size\n");
+ s->num_streams = 0;
return AVERROR(EINVAL);
}
} else if (avctx->codec_id == AV_CODEC_ID_XMA1 && avctx->extradata_size >= 4) { /* XMAWAVEFORMAT */
s->num_streams = avctx->extradata[4];
if (avctx->extradata_size != (8 + 20*s->num_streams)) {
av_log(avctx, AV_LOG_ERROR, "Incorrect XMA1 extradata size\n");
+ s->num_streams = 0;
return AVERROR(EINVAL);
}
} else {
}
/* encoder supports up to 64 streams / 64*2 channels (would have to alloc arrays) */
- if (avctx->channels > XMA_MAX_CHANNELS || s->num_streams > XMA_MAX_STREAMS) {
+ if (avctx->channels > XMA_MAX_CHANNELS || s->num_streams > XMA_MAX_STREAMS ||
+ s->num_streams <= 0
+ ) {
avpriv_request_sample(avctx, "More than %d channels in %d streams", XMA_MAX_CHANNELS, s->num_streams);
+ s->num_streams = 0;
return AVERROR_PATCHWELCOME;
}
s->frames[i] = av_frame_alloc();
if (!s->frames[i])
return AVERROR(ENOMEM);
- s->frames[i]->nb_samples = 512;
- if ((ret = ff_get_buffer(avctx, s->frames[i], 0)) < 0) {
- return AVERROR(ENOMEM);
- }
s->start_channel[i] = start_channels;
start_channels += s->xma[i].nb_channels;
}
+ if (start_channels != avctx->channels)
+ return AVERROR_INVALIDDATA;
return ret;
}
decode_end(&s->xma[i]);
av_frame_free(&s->frames[i]);
}
+ s->num_streams = 0;
return 0;
}
/**
*@brief wmapro decoder
*/
-AVCodec ff_wmapro_decoder = {
+const AVCodec ff_wmapro_decoder = {
.name = "wmapro",
.long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 9 Professional"),
.type = AVMEDIA_TYPE_AUDIO,
.close = wmapro_decode_end,
.decode = wmapro_decode_packet,
.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1,
+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
.flush = wmapro_flush,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
};
-AVCodec ff_xma1_decoder = {
+const AVCodec ff_xma1_decoder = {
.name = "xma1",
.long_name = NULL_IF_CONFIG_SMALL("Xbox Media Audio 1"),
.type = AVMEDIA_TYPE_AUDIO,
.close = xma_decode_end,
.decode = xma_decode_packet,
.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
};
-AVCodec ff_xma2_decoder = {
+const AVCodec ff_xma2_decoder = {
.name = "xma2",
.long_name = NULL_IF_CONFIG_SMALL("Xbox Media Audio 2"),
.type = AVMEDIA_TYPE_AUDIO,
.decode = xma_decode_packet,
.flush = xma_flush,
.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
};