#include <string.h>
#include "libavutil/intreadwrite.h"
+#include "libavutil/mem.h"
#include "avcodec.h"
#include "bytestream.h"
-#define ALT_BITSTREAM_READER_LE
+#define BITSTREAM_READER_LE
#include "get_bits.h"
-// for av_memcpy_backptr
-#include "libavutil/lzo.h"
+#include "internal.h"
#define RUNTIME_GAMMA 0
s->avctx = avctx;
s->frame_size = 0;
- avctx->pix_fmt = PIX_FMT_PAL8;
+ avctx->pix_fmt = AV_PIX_FMT_PAL8;
s->buffer1_size = avctx->width * avctx->height;
s->buffer1 = av_malloc(s->buffer1_size);
init_get_bits(&gb, ptr, ptr_len * 8);
- while ( val != 0x16 ) {
- val = src[val - 0x17 + get_bits1(&gb) * byte];
+ while (val != 0x16) {
+ unsigned idx = val - 0x17 + get_bits1(&gb) * byte;
+ if (idx >= 2 * byte)
+ return AVERROR_INVALIDDATA;
+ val = src[idx];
- if ( val < 0x16 ) {
+ if (val < 0x16) {
if (dest >= dest_end)
return 0;
*dest++ = val;
int size;
unsigned char *dest_org = dest;
unsigned char *dest_end = dest + dest_len;
- const unsigned char *src_end = src + src_len;
+ GetByteContext ctx;
- while (dest < dest_end && src < src_end) {
- opcode = *src++;
+ bytestream2_init(&ctx, src, src_len);
+ while (dest < dest_end && bytestream2_get_bytes_left(&ctx)) {
+ opcode = bytestream2_get_byte(&ctx);
if (opcode < 0xe0) {
int size2, back;
- if ( (opcode & 0x80) == 0 ) {
-
+ if ((opcode & 0x80) == 0) {
size = opcode & 3;
- back = ((opcode & 0x60) << 3) + *src++ + 1;
+ back = ((opcode & 0x60) << 3) + bytestream2_get_byte(&ctx) + 1;
size2 = ((opcode & 0x1c) >> 2) + 3;
+ } else if ((opcode & 0x40) == 0) {
+ size = bytestream2_peek_byte(&ctx) >> 6;
- } else if ( (opcode & 0x40) == 0 ) {
-
- size = *src >> 6;
-
- back = (bytestream_get_be16(&src) & 0x3fff) + 1;
+ back = (bytestream2_get_be16(&ctx) & 0x3fff) + 1;
size2 = (opcode & 0x3f) + 4;
-
} else {
-
size = opcode & 3;
- back = ((opcode & 0x10) << 12) + bytestream_get_be16(&src) + 1;
- size2 = ((opcode & 0x0c) << 6) + *src++ + 5;
+ back = ((opcode & 0x10) << 12) + bytestream2_get_be16(&ctx) + 1;
+ size2 = ((opcode & 0x0c) << 6) + bytestream2_get_byte(&ctx) + 5;
}
+
if (dest_end - dest < size + size2 ||
dest + size - dest_org < back ||
- src_end - src < size)
+ bytestream2_get_bytes_left(&ctx) < size)
return;
- memcpy(dest, src, size); dest += size; src += size;
+ bytestream2_get_buffer(&ctx, dest, size);
+ dest += size;
av_memcpy_backptr(dest, back, size2);
dest += size2;
} else {
int finish = opcode >= 0xfc;
size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4;
- if (dest_end - dest < size || src_end - src < size)
+ if (dest_end - dest < size || bytestream2_get_bytes_left(&ctx) < size)
return;
- memcpy(dest, src, size); dest += size; src += size;
+ bytestream2_get_buffer(&ctx, dest, size);
+ dest += size;
if (finish)
return;
}
line_inc = stride - width;
index = y * stride + x;
current_x = x;
- while(pixel_count && (index < s->frame_size)) {
+ while (pixel_count && index < s->frame_size) {
int count = FFMIN(pixel_count, width - current_x);
memcpy(palette_plane + index, pixel_buffer, count);
pixel_count -= count;
}
}
-static inline void xan_wc3_copy_pixel_run(XanContext *s,
- int x, int y, int pixel_count, int motion_x, int motion_y)
+static inline void xan_wc3_copy_pixel_run(XanContext *s, int x, int y,
+ int pixel_count, int motion_x,
+ int motion_y)
{
int stride;
int line_inc;
int width = s->avctx->width;
unsigned char *palette_plane, *prev_palette_plane;
- if ( y + motion_y < 0 || y + motion_y >= s->avctx->height ||
- x + motion_x < 0 || x + motion_x >= s->avctx->width)
+ if (y + motion_y < 0 || y + motion_y >= s->avctx->height ||
+ x + motion_x < 0 || x + motion_x >= s->avctx->width)
return;
palette_plane = s->current_frame.data[0];
curframe_x = x;
prevframe_index = (y + motion_y) * stride + x + motion_x;
prevframe_x = x + motion_x;
- while(pixel_count &&
- curframe_index < s->frame_size &&
- prevframe_index < s->frame_size) {
- int count = FFMIN3(pixel_count, width - curframe_x, width - prevframe_x);
-
- memcpy(palette_plane + curframe_index, prev_palette_plane + prevframe_index, count);
+ while (pixel_count &&
+ curframe_index < s->frame_size &&
+ prevframe_index < s->frame_size) {
+ int count = FFMIN3(pixel_count, width - curframe_x,
+ width - prevframe_x);
+
+ memcpy(palette_plane + curframe_index,
+ prev_palette_plane + prevframe_index, count);
pixel_count -= count;
curframe_index += count;
prevframe_index += count;
static int xan_wc3_decode_frame(XanContext *s) {
- int width = s->avctx->width;
+ int width = s->avctx->width;
int height = s->avctx->height;
int total_pixels = width * height;
unsigned char opcode;
const unsigned char *size_segment;
const unsigned char *vector_segment;
const unsigned char *imagedata_segment;
- int huffman_offset, size_offset, vector_offset, imagedata_offset, imagedata_size;
+ int huffman_offset, size_offset, vector_offset, imagedata_offset,
+ imagedata_size;
if (s->size < 8)
return AVERROR_INVALIDDATA;
size_segment += 3;
break;
}
+
if (size > total_pixels)
break;
#endif
static int xan_decode_frame(AVCodecContext *avctx,
- void *data, int *data_size,
+ void *data, int *got_frame,
AVPacket *avpkt)
{
const uint8_t *buf = avpkt->data;
int ret, buf_size = avpkt->size;
XanContext *s = avctx->priv_data;
-
- if (avctx->codec->id == CODEC_ID_XAN_WC3) {
- const uint8_t *buf_end = buf + buf_size;
- int tag = 0;
- while (buf_end - buf > 8 && tag != VGA__TAG) {
- unsigned *tmpptr;
- uint32_t new_pal;
- int size;
- int i;
- tag = bytestream_get_le32(&buf);
- size = bytestream_get_be32(&buf);
- size = FFMIN(size, buf_end - buf);
- switch (tag) {
- case PALT_TAG:
- if (size < PALETTE_SIZE)
- return AVERROR_INVALIDDATA;
- if (s->palettes_count >= PALETTES_MAX)
- return AVERROR_INVALIDDATA;
- tmpptr = av_realloc(s->palettes, (s->palettes_count + 1) * AVPALETTE_SIZE);
- if (!tmpptr)
- return AVERROR(ENOMEM);
- s->palettes = tmpptr;
- tmpptr += s->palettes_count * AVPALETTE_COUNT;
- for (i = 0; i < PALETTE_COUNT; i++) {
+ GetByteContext ctx;
+ int tag = 0;
+
+ bytestream2_init(&ctx, buf, buf_size);
+ while (bytestream2_get_bytes_left(&ctx) > 8 && tag != VGA__TAG) {
+ unsigned *tmpptr;
+ uint32_t new_pal;
+ int size;
+ int i;
+ tag = bytestream2_get_le32(&ctx);
+ size = bytestream2_get_be32(&ctx);
+ size = FFMIN(size, bytestream2_get_bytes_left(&ctx));
+ switch (tag) {
+ case PALT_TAG:
+ if (size < PALETTE_SIZE)
+ return AVERROR_INVALIDDATA;
+ if (s->palettes_count >= PALETTES_MAX)
+ return AVERROR_INVALIDDATA;
+ tmpptr = av_realloc(s->palettes,
+ (s->palettes_count + 1) * AVPALETTE_SIZE);
+ if (!tmpptr)
+ return AVERROR(ENOMEM);
+ s->palettes = tmpptr;
+ tmpptr += s->palettes_count * AVPALETTE_COUNT;
+ for (i = 0; i < PALETTE_COUNT; i++) {
#if RUNTIME_GAMMA
- int r = gamma_corr(*buf++);
- int g = gamma_corr(*buf++);
- int b = gamma_corr(*buf++);
+ int r = gamma_corr(bytestream2_get_byteu(&ctx));
+ int g = gamma_corr(bytestream2_get_byteu(&ctx));
+ int b = gamma_corr(bytestream2_get_byteu(&ctx));
#else
- int r = gamma_lookup[*buf++];
- int g = gamma_lookup[*buf++];
- int b = gamma_lookup[*buf++];
+ int r = gamma_lookup[bytestream2_get_byteu(&ctx)];
+ int g = gamma_lookup[bytestream2_get_byteu(&ctx)];
+ int b = gamma_lookup[bytestream2_get_byteu(&ctx)];
#endif
- *tmpptr++ = (r << 16) | (g << 8) | b;
- }
- s->palettes_count++;
- break;
- case SHOT_TAG:
- if (size < 4)
- return AVERROR_INVALIDDATA;
- new_pal = bytestream_get_le32(&buf);
- if (new_pal < s->palettes_count) {
- s->cur_palette = new_pal;
- } else
- av_log(avctx, AV_LOG_ERROR, "Invalid palette selected\n");
- break;
- case VGA__TAG:
- break;
- default:
- buf += size;
- break;
+ *tmpptr++ = (r << 16) | (g << 8) | b;
}
+ s->palettes_count++;
+ break;
+ case SHOT_TAG:
+ if (size < 4)
+ return AVERROR_INVALIDDATA;
+ new_pal = bytestream2_get_le32(&ctx);
+ if (new_pal < s->palettes_count) {
+ s->cur_palette = new_pal;
+ } else
+ av_log(avctx, AV_LOG_ERROR, "Invalid palette selected\n");
+ break;
+ case VGA__TAG:
+ break;
+ default:
+ bytestream2_skip(&ctx, size);
+ break;
}
- buf_size = buf_end - buf;
}
- if ((ret = avctx->get_buffer(avctx, &s->current_frame))) {
+ buf_size = bytestream2_get_bytes_left(&ctx);
+
+ if (s->palettes_count <= 0) {
+ av_log(s->avctx, AV_LOG_ERROR, "No palette found\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ if ((ret = ff_get_buffer(avctx, &s->current_frame))) {
av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return ret;
}
if (!s->frame_size)
s->frame_size = s->current_frame.linesize[0] * s->avctx->height;
- memcpy(s->current_frame.data[1], s->palettes + s->cur_palette * AVPALETTE_COUNT, AVPALETTE_SIZE);
+ memcpy(s->current_frame.data[1],
+ s->palettes + s->cur_palette * AVPALETTE_COUNT, AVPALETTE_SIZE);
- s->buf = buf;
+ s->buf = ctx.buffer;
s->size = buf_size;
if (xan_wc3_decode_frame(s) < 0)
if (s->last_frame.data[0])
avctx->release_buffer(avctx, &s->last_frame);
- *data_size = sizeof(AVFrame);
+ *got_frame = 1;
*(AVFrame*)data = s->current_frame;
/* shuffle frames */
AVCodec ff_xan_wc3_decoder = {
.name = "xan_wc3",
.type = AVMEDIA_TYPE_VIDEO,
- .id = CODEC_ID_XAN_WC3,
+ .id = AV_CODEC_ID_XAN_WC3,
.priv_data_size = sizeof(XanContext),
.init = xan_decode_init,
.close = xan_decode_end,
.decode = xan_decode_frame,
.capabilities = CODEC_CAP_DR1,
- .long_name = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"),
+ .long_name = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"),
};