|
|
@@ -45,43 +45,43 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data, |
|
|
|
uint32_t pixformat, pixdepth, bunit, bitorder, bpad; |
|
|
|
uint32_t rgb[3]; |
|
|
|
uint8_t *ptr; |
|
|
|
GetByteContext gb; |
|
|
|
|
|
|
|
if (buf_size < XWD_HEADER_SIZE) |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
|
|
|
header_size = bytestream_get_be32(&buf); |
|
|
|
if (buf_size < header_size) |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
bytestream2_init(&gb, buf, buf_size); |
|
|
|
header_size = bytestream2_get_be32u(&gb); |
|
|
|
|
|
|
|
version = bytestream_get_be32(&buf); |
|
|
|
version = bytestream2_get_be32u(&gb); |
|
|
|
if (version != XWD_VERSION) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "unsupported version\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
if (header_size < XWD_HEADER_SIZE) { |
|
|
|
if (buf_size < header_size || header_size < XWD_HEADER_SIZE) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "invalid header size\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
pixformat = bytestream_get_be32(&buf); |
|
|
|
pixdepth = bytestream_get_be32(&buf); |
|
|
|
avctx->width = bytestream_get_be32(&buf); |
|
|
|
avctx->height = bytestream_get_be32(&buf); |
|
|
|
xoffset = bytestream_get_be32(&buf); |
|
|
|
be = bytestream_get_be32(&buf); |
|
|
|
bunit = bytestream_get_be32(&buf); |
|
|
|
bitorder = bytestream_get_be32(&buf); |
|
|
|
bpad = bytestream_get_be32(&buf); |
|
|
|
bpp = bytestream_get_be32(&buf); |
|
|
|
lsize = bytestream_get_be32(&buf); |
|
|
|
vclass = bytestream_get_be32(&buf); |
|
|
|
rgb[0] = bytestream_get_be32(&buf); |
|
|
|
rgb[1] = bytestream_get_be32(&buf); |
|
|
|
rgb[2] = bytestream_get_be32(&buf); |
|
|
|
buf += 8; |
|
|
|
ncolors = bytestream_get_be32(&buf); |
|
|
|
buf += header_size - (XWD_HEADER_SIZE - 20); |
|
|
|
pixformat = bytestream2_get_be32u(&gb); |
|
|
|
pixdepth = bytestream2_get_be32u(&gb); |
|
|
|
avctx->width = bytestream2_get_be32u(&gb); |
|
|
|
avctx->height = bytestream2_get_be32u(&gb); |
|
|
|
xoffset = bytestream2_get_be32u(&gb); |
|
|
|
be = bytestream2_get_be32u(&gb); |
|
|
|
bunit = bytestream2_get_be32u(&gb); |
|
|
|
bitorder = bytestream2_get_be32u(&gb); |
|
|
|
bpad = bytestream2_get_be32u(&gb); |
|
|
|
bpp = bytestream2_get_be32u(&gb); |
|
|
|
lsize = bytestream2_get_be32u(&gb); |
|
|
|
vclass = bytestream2_get_be32u(&gb); |
|
|
|
rgb[0] = bytestream2_get_be32u(&gb); |
|
|
|
rgb[1] = bytestream2_get_be32u(&gb); |
|
|
|
rgb[2] = bytestream2_get_be32u(&gb); |
|
|
|
bytestream2_skipu(&gb, 8); |
|
|
|
ncolors = bytestream2_get_be32u(&gb); |
|
|
|
bytestream2_skipu(&gb, header_size - (XWD_HEADER_SIZE - 20)); |
|
|
|
|
|
|
|
av_log(avctx, AV_LOG_DEBUG, "pixformat %d, pixdepth %d, bunit %d, bitorder %d, bpad %d\n", |
|
|
|
pixformat, pixdepth, bunit, bitorder, bpad); |
|
|
@@ -143,7 +143,7 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data, |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
if (buf_size < header_size + ncolors * XWD_CMAP_SIZE + avctx->height * lsize) { |
|
|
|
if (bytestream2_get_bytes_left(&gb) < ncolors * XWD_CMAP_SIZE + avctx->height * lsize) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "input buffer too small\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
@@ -192,7 +192,7 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data, |
|
|
|
else if (rgb[0] == 0xFF && rgb[1] == 0xFF00 && rgb[2] == 0xFF0000) |
|
|
|
avctx->pix_fmt = be ? PIX_FMT_ABGR : PIX_FMT_RGBA; |
|
|
|
} |
|
|
|
buf += ncolors * XWD_CMAP_SIZE; |
|
|
|
bytestream2_skipu(&gb, ncolors * XWD_CMAP_SIZE); |
|
|
|
break; |
|
|
|
default: |
|
|
|
av_log(avctx, AV_LOG_ERROR, "invalid visual class\n"); |
|
|
@@ -222,11 +222,13 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data, |
|
|
|
|
|
|
|
for (i = 0; i < ncolors; i++) { |
|
|
|
|
|
|
|
buf += 4; // skip colormap entry number |
|
|
|
red = *buf; buf += 2; |
|
|
|
green = *buf; buf += 2; |
|
|
|
blue = *buf; buf += 2; |
|
|
|
buf += 2; // skip bitmask flag and padding |
|
|
|
bytestream2_skipu(&gb, 4); // skip colormap entry number |
|
|
|
red = bytestream2_get_byteu(&gb); |
|
|
|
bytestream2_skipu(&gb, 1); |
|
|
|
green = bytestream2_get_byteu(&gb); |
|
|
|
bytestream2_skipu(&gb, 1); |
|
|
|
blue = bytestream2_get_byteu(&gb); |
|
|
|
bytestream2_skipu(&gb, 3); // skip bitmask flag and padding |
|
|
|
|
|
|
|
dst[i] = red << 16 | green << 8 | blue; |
|
|
|
} |
|
|
@@ -234,8 +236,8 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data, |
|
|
|
|
|
|
|
ptr = p->data[0]; |
|
|
|
for (i = 0; i < avctx->height; i++) { |
|
|
|
bytestream_get_buffer(&buf, ptr, rsize); |
|
|
|
buf += lsize - rsize; |
|
|
|
bytestream2_get_bufferu(&gb, ptr, rsize); |
|
|
|
bytestream2_skipu(&gb, lsize - rsize); |
|
|
|
ptr += p->linesize[0]; |
|
|
|
} |
|
|
|
|
|
|
|