aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec/vmdav.c
diff options
context:
space:
mode:
authorKostya Shishkov <kostya.shishkov@gmail.com>2013-06-01 19:19:28 +0200
committerKostya Shishkov <kostya.shishkov@gmail.com>2013-06-02 19:07:31 +0200
commit0aed0bfc62b273a780a2bfba3be56039fccd7423 (patch)
treec98f37fac8db1c96a82955c59f889092cbad3819 /libavcodec/vmdav.c
parentc011ceef78eae66039efc66d9551a7146e08838a (diff)
downloadffmpeg-0aed0bfc62b273a780a2bfba3be56039fccd7423.tar.gz
vmd: fix mode 3 decoding
Diffstat (limited to 'libavcodec/vmdav.c')
-rw-r--r--libavcodec/vmdav.c30
1 files 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])