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

Reply via email to