* 4XM codec.
*/
+#include "libavutil/avassert.h"
#include "libavutil/frame.h"
+ #include "libavutil/imgutils.h"
#include "libavutil/intreadwrite.h"
#include "avcodec.h"
#include "bytestream.h"
bytestream_offset, wordstream_offset;
int ret;
- if (!f->last_picture->data[0]) {
- if ((ret = ff_get_buffer(f->avctx, f->last_picture,
- AV_GET_BUFFER_FLAG_REF)) < 0) {
- return ret;
- }
- for (y=0; y<f->avctx->height; y++)
- memset(f->last_picture->data[0] + y*f->last_picture->linesize[0], 0, 2*f->avctx->width);
- }
-
- src = (uint16_t *)f->last_picture->data[0];
+ src = f->last_frame_buffer;
if (f->version > 1) {
- if (length < 20)
- return AVERROR_INVALIDDATA;
extra = 20;
+ if (length < extra)
+ return AVERROR_INVALIDDATA;
bitstream_size = AV_RL32(buf + 8);
wordstream_size = AV_RL32(buf + 12);
bytestream_size = AV_RL32(buf + 16);
const int width = f->avctx->width;
const int height = f->avctx->height;
const int mbs = (FFALIGN(width, 16) >> 4) * (FFALIGN(height, 16) >> 4);
- uint16_t *dst = (uint16_t*)frame->data[0];
- const int stride = frame->linesize[0]>>1;
+ uint16_t *dst = f->frame_buffer;
+ const uint8_t *buf_end = buf + length;
GetByteContext g3;
if (length < mbs * 8) {
frame_size = buf_size - 12;
}
- FFSWAP(AVFrame*, f->current_picture, f->last_picture);
-
- // alternatively we would have to use our own buffer management
- avctx->flags |= CODEC_FLAG_EMU_EDGE;
--
- if ((ret = ff_reget_buffer(avctx, f->current_picture)) < 0)
- if ((ret = ff_get_buffer(avctx, picture, 0)) < 0) {
- av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
++ if ((ret = ff_get_buffer(avctx, picture, 0)) < 0)
return ret;
- }
if (frame_4cc == AV_RL32("ifr2")) {
- f->current_picture->pict_type = AV_PICTURE_TYPE_I;
- if ((ret = decode_i2_frame(f, f->current_picture, buf - 4, frame_size + 4)) < 0) {
+ picture->pict_type = AV_PICTURE_TYPE_I;
- if ((ret = decode_i2_frame(f, buf - 4, frame_size + 4)) < 0)
++ if ((ret = decode_i2_frame(f, buf - 4, frame_size + 4)) < 0) {
+ av_log(f->avctx, AV_LOG_ERROR, "decode i2 frame failed\n");
return ret;
+ }
} else if (frame_4cc == AV_RL32("ifrm")) {
- f->current_picture->pict_type = AV_PICTURE_TYPE_I;
- if ((ret = decode_i_frame(f, f->current_picture, buf, frame_size)) < 0) {
+ picture->pict_type = AV_PICTURE_TYPE_I;
- if ((ret = decode_i_frame(f, buf, frame_size)) < 0)
++ if ((ret = decode_i_frame(f, buf, frame_size)) < 0) {
+ av_log(f->avctx, AV_LOG_ERROR, "decode i frame failed\n");
return ret;
+ }
} else if (frame_4cc == AV_RL32("pfrm") || frame_4cc == AV_RL32("pfr2")) {
- f->current_picture->pict_type = AV_PICTURE_TYPE_P;
- if ((ret = decode_p_frame(f, f->current_picture, buf, frame_size)) < 0) {
+ picture->pict_type = AV_PICTURE_TYPE_P;
- if ((ret = decode_p_frame(f, buf, frame_size)) < 0)
++ if ((ret = decode_p_frame(f, buf, frame_size)) < 0) {
+ av_log(f->avctx, AV_LOG_ERROR, "decode p frame failed\n");
return ret;
+ }
} else if (frame_4cc == AV_RL32("snd_")) {
av_log(avctx, AV_LOG_ERROR, "ignoring snd_ chunk length:%d\n",
buf_size);
av_log(avctx, AV_LOG_ERROR, "extradata wrong or missing\n");
return AVERROR_INVALIDDATA;
}
+ if((avctx->width % 16) || (avctx->height % 16)) {
+ av_log(avctx, AV_LOG_ERROR, "unsupported width/height\n");
+ return AVERROR_INVALIDDATA;
+ }
+ ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
+ if (ret < 0)
+ return ret;
+
+ f->frame_buffer = av_mallocz(avctx->width * avctx->height * 2);
+ f->last_frame_buffer = av_mallocz(avctx->width * avctx->height * 2);
+ if (!f->frame_buffer || !f->last_frame_buffer) {
+ decode_end(avctx);
+ return AVERROR(ENOMEM);
+ }
+
f->version = AV_RL32(avctx->extradata) >> 16;
ff_dsputil_init(&f->dsp, avctx);
f->avctx = avctx;