Put the three modes in separate functions.
---
libavcodec/vmdvideo.c | 180 +++++++++++++++++++++++++++++---------------------
1 file changed, 106 insertions(+), 74 deletions(-)
diff --git a/libavcodec/vmdvideo.c b/libavcodec/vmdvideo.c
index aaeff43..4a14ef0 100644
--- a/libavcodec/vmdvideo.c
+++ b/libavcodec/vmdvideo.c
@@ -179,6 +179,106 @@ static int rle_unpack(const unsigned char *src, unsigned
char *dest,
return bytestream2_tell(&gb);
}
+static int copy_region(VmdVideoContext *s, GetByteContext *gb,
+ uint8_t *dp, uint8_t *pp,
+ int frame_width, int frame_height,
+ int frame_linesize)
+{
+ int i, len, ofs;
+ for (i = 0; i < frame_height; i++) {
+ ofs = 0;
+ do {
+ len = bytestream2_get_byte(gb);
+ if (len & 0x80) {
+ len = (len & 0x7F) + 1;
+ if (ofs + len > frame_width ||
+ bytestream2_get_bytes_left(gb) < len)
+ return AVERROR_INVALIDDATA;
+ bytestream2_get_buffer(gb, &dp[ofs], len);
+ ofs += len;
+ } else {
+ /* interframe pixel copy */
+ if (ofs + len + 1 > frame_width || !s->prev_frame->data[0])
+ return AVERROR_INVALIDDATA;
+ memcpy(&dp[ofs], &pp[ofs], len + 1);
+ ofs += len + 1;
+ }
+ } while (ofs < frame_width);
+ if (ofs > frame_width) {
+ av_log(s->avctx, AV_LOG_ERROR,
+ "VMD video: offset > width (%d > %d)\n",
+ ofs, frame_width);
+ return AVERROR_INVALIDDATA;
+ }
+ dp += frame_linesize;
+ pp += s->prev_frame->linesize[0];
+ }
+ return 0;
+}
+
+static int copy_frame(VmdVideoContext *s, GetByteContext *gb,
+ uint8_t *dp, uint8_t *pp,
+ int frame_width, int frame_height,
+ int frame_linesize)
+{
+ int i;
+
+ for (i = 0; i < frame_height; i++) {
+ bytestream2_get_buffer(gb, dp, frame_width);
+ dp += frame_linesize;
+ pp += s->prev_frame->linesize[0];
+ }
+
+ return 0;
+}
+
+static int rle_region(VmdVideoContext *s, GetByteContext *gb,
+ uint8_t *dp, uint8_t *pp,
+ int frame_width, int frame_height,
+ int frame_linesize)
+{
+ int i, len, ofs;
+
+ for (i = 0; i < frame_height; i++) {
+ ofs = 0;
+ do {
+ len = bytestream2_get_byte(gb);
+ if (len & 0x80) {
+ len = (len & 0x7F) + 1;
+ 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);
+ ofs += slen;
+ bytestream2_skip(gb, len);
+ } else {
+ bytestream2_get_buffer(gb, &dp[ofs], len);
+ ofs += len;
+ }
+ } else {
+ /* interframe pixel copy */
+ if (ofs + len + 1 > frame_width || !s->prev_frame->data[0])
+ return AVERROR_INVALIDDATA;
+ memcpy(&dp[ofs], &pp[ofs], len + 1);
+ ofs += len + 1;
+ }
+ } while (ofs < frame_width);
+ if (ofs > frame_width) {
+ av_log(s->avctx, AV_LOG_ERROR,
+ "VMD video: offset > width (%d > %d)\n",
+ ofs, frame_width);
+ return AVERROR_INVALIDDATA;
+ }
+ dp += frame_linesize;
+ pp += s->prev_frame->linesize[0];
+ }
+
+ return 0;
+}
+
+
static int vmd_decode(VmdVideoContext *s, AVFrame *frame)
{
int i;
@@ -190,8 +290,6 @@ static int vmd_decode(VmdVideoContext *s, AVFrame *frame)
unsigned char meth;
unsigned char *dp; /* pointer to current frame */
unsigned char *pp; /* pointer to previous frame */
- unsigned char len;
- int ofs;
int frame_x, frame_y;
int frame_width, frame_height;
@@ -280,81 +378,15 @@ static int vmd_decode(VmdVideoContext *s, AVFrame *frame)
pp = &s->prev_frame->data[0][frame_y * s->prev_frame->linesize[0] +
frame_x];
switch (meth) {
case 1:
- for (i = 0; i < frame_height; i++) {
- ofs = 0;
- do {
- len = bytestream2_get_byte(&gb);
- if (len & 0x80) {
- len = (len & 0x7F) + 1;
- if (ofs + len > frame_width ||
- bytestream2_get_bytes_left(&gb) < len)
- return AVERROR_INVALIDDATA;
- bytestream2_get_buffer(&gb, &dp[ofs], len);
- ofs += len;
- } else {
- /* interframe pixel copy */
- if (ofs + len + 1 > frame_width || !s->prev_frame->data[0])
- return AVERROR_INVALIDDATA;
- memcpy(&dp[ofs], &pp[ofs], len + 1);
- ofs += len + 1;
- }
- } while (ofs < frame_width);
- if (ofs > frame_width) {
- av_log(s->avctx, AV_LOG_ERROR,
- "VMD video: offset > width (%d > %d)\n",
- ofs, frame_width);
- return AVERROR_INVALIDDATA;
- }
- dp += frame->linesize[0];
- pp += s->prev_frame->linesize[0];
- }
- break;
+ return copy_region(s, &gb, dp, pp, frame_width, frame_height,
+ frame->linesize[0]);
case 2:
- for (i = 0; i < frame_height; i++) {
- bytestream2_get_buffer(&gb, dp, frame_width);
- dp += frame->linesize[0];
- pp += s->prev_frame->linesize[0];
- }
- break;
-
+ return copy_frame(s, &gb, dp, pp, frame_width, frame_height,
+ frame->linesize[0]);
case 3:
- for (i = 0; i < frame_height; i++) {
- ofs = 0;
- do {
- len = bytestream2_get_byte(&gb);
- if (len & 0x80) {
- len = (len & 0x7F) + 1;
- 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);
- ofs += slen;
- bytestream2_skip(&gb, len);
- } else {
- bytestream2_get_buffer(&gb, &dp[ofs], len);
- ofs += len;
- }
- } else {
- /* interframe pixel copy */
- if (ofs + len + 1 > frame_width || !s->prev_frame->data[0])
- return AVERROR_INVALIDDATA;
- memcpy(&dp[ofs], &pp[ofs], len + 1);
- ofs += len + 1;
- }
- } while (ofs < frame_width);
- if (ofs > frame_width) {
- av_log(s->avctx, AV_LOG_ERROR,
- "VMD video: offset > width (%d > %d)\n",
- ofs, frame_width);
- return AVERROR_INVALIDDATA;
- }
- dp += frame->linesize[0];
- pp += s->prev_frame->linesize[0];
- }
- break;
+ return rle_region(s, &gb, dp, pp, frame_width, frame_height,
+ frame->linesize[0]);
}
return 0;
}
--
1.9.0
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel