From 0aed0bfc62b273a780a2bfba3be56039fccd7423 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Sat, 1 Jun 2013 19:19:28 +0200 Subject: [PATCH] vmd: fix mode 3 decoding --- libavcodec/vmdav.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/libavcodec/vmdav.c b/libavcodec/vmdav.c index 3a0cbf9424..58cd4ab6ff 100644 --- a/libavcodec/vmdav.c +++ b/libavcodec/vmdav.c @@ -152,9 +152,10 @@ static int rle_unpack(const unsigned char *src, unsigned char *dest, int src_count, int src_size, int dest_len) { unsigned char *pd; - int i, l; + int i, l, used = 0; unsigned char *dest_end = dest + dest_len; GetByteContext gb; + uint16_t run_val; bytestream2_init(&gb, src, src_size); pd = dest; @@ -162,10 +163,9 @@ static int rle_unpack(const unsigned char *src, unsigned char *dest, if (bytestream2_get_bytes_left(&gb) < 1) return 0; *pd++ = bytestream2_get_byteu(&gb); + used++; } - src_count >>= 1; - i = 0; do { if (bytestream2_get_bytes_left(&gb) < 1) break; @@ -177,16 +177,17 @@ static int rle_unpack(const unsigned char *src, unsigned char *dest, bytestream2_get_buffer(&gb, pd, l); pd += l; } else { - if (pd + i > dest_end || bytestream2_get_bytes_left(&gb) < 2) + if (pd + l > dest_end || bytestream2_get_bytes_left(&gb) < 2) return bytestream2_tell(&gb); + run_val = bytestream2_get_ne16(&gb); for (i = 0; i < l; i++) { - *pd++ = bytestream2_get_byteu(&gb); - *pd++ = bytestream2_get_byteu(&gb); + AV_WN16(pd, run_val); + pd += 2; } - bytestream2_skip(&gb, 2); + l *= 2; } - i += l; - } while (i < src_count); + used += l; + } while (used < src_count); return bytestream2_tell(&gb); } @@ -332,13 +333,18 @@ static int vmd_decode(VmdVideoContext *s, AVFrame *frame) len = bytestream2_get_byte(&gb); if (len & 0x80) { len = (len & 0x7F) + 1; - if (bytestream2_get_byte(&gb) == 0xFF) + if (bytestream2_peek_byte(&gb) == 0xFF) { + int slen = len; + bytestream2_get_byte(&gb); len = rle_unpack(gb.buffer, &dp[ofs], len, bytestream2_get_bytes_left(&gb), frame_width - ofs); - else + ofs += slen; + bytestream2_skip(&gb, len); + } else { bytestream2_get_buffer(&gb, &dp[ofs], len); - bytestream2_skip(&gb, len); + ofs += len; + } } else { /* interframe pixel copy */ if (ofs + len + 1 > frame_width || !s->prev_frame.data[0])