changeset 1609:7f4d1ab4ac17 libavcodec

4bpp support
author rtognimp
date Sun, 09 Nov 2003 21:54:49 +0000
parents 639972344c6f
children b0fe2a0adf49
files msrle.c
diffstat 1 files changed, 106 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/msrle.c	Fri Nov 07 22:39:18 2003 +0000
+++ b/msrle.c	Sun Nov 09 21:54:49 2003 +0000
@@ -56,6 +56,101 @@
     } \
     stream_byte = s->buf[stream_ptr++];
 
+static void msrle_decode_pal4(MsrleContext *s)
+{
+    int stream_ptr = 0;
+    unsigned char rle_code;
+    unsigned char extra_byte, odd_pixel;
+    unsigned char stream_byte;
+    int pixel_ptr = 0;
+    int row_dec = s->frame.linesize[0];
+    int row_ptr = (s->avctx->height - 1) * row_dec;
+    int frame_size = row_dec * s->avctx->height;
+    int i;
+
+    /* make the palette available */
+    memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
+    if (s->avctx->palctrl->palette_changed) {
+        s->frame.palette_has_changed = 1;
+        s->avctx->palctrl->palette_changed = 0;
+    }
+
+    while (row_ptr >= 0) {
+        FETCH_NEXT_STREAM_BYTE();
+        rle_code = stream_byte;
+        if (rle_code == 0) {
+            /* fetch the next byte to see how to handle escape code */
+            FETCH_NEXT_STREAM_BYTE();
+            if (stream_byte == 0) {
+                /* line is done, goto the next one */
+                row_ptr -= row_dec;
+                pixel_ptr = 0;
+            } else if (stream_byte == 1) {
+                /* decode is done */
+                return;
+            } else if (stream_byte == 2) {
+                /* reposition frame decode coordinates */
+                FETCH_NEXT_STREAM_BYTE();
+                pixel_ptr += stream_byte;
+                FETCH_NEXT_STREAM_BYTE();
+                row_ptr -= stream_byte * row_dec;
+        } else {
+            // copy pixels from encoded stream
+            odd_pixel =  stream_byte & 1;
+            rle_code = (stream_byte + 1) / 2;
+            extra_byte = rle_code & 0x01;
+            if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
+                (row_ptr < 0)) {
+                av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
+                return;
+            }
+
+            for (i = 0; i < rle_code; i++) {
+                if (pixel_ptr >= s->avctx->width)
+                    break;
+                FETCH_NEXT_STREAM_BYTE();
+                s->frame.data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
+                pixel_ptr++;
+      	      if (i + 1 == rle_code && odd_pixel)
+        	        break;
+                if (pixel_ptr >= s->avctx->width)
+                    break;
+                s->frame.data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
+                pixel_ptr++;
+            }
+
+            // if the RLE code is odd, skip a byte in the stream
+            if (extra_byte)
+              stream_ptr++;
+            }
+        } else {
+            // decode a run of data
+            if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
+                (row_ptr < 0)) {
+                av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
+                return;
+            }
+            FETCH_NEXT_STREAM_BYTE();
+            for (i = 0; i < rle_code; i++) {
+                if (pixel_ptr >= s->avctx->width)
+                    break;
+                if ((i & 1) == 0)
+                    s->frame.data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
+                else
+                    s->frame.data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
+                pixel_ptr++;
+            }
+        }
+    }
+
+    /* one last sanity check on the way out */
+    if (stream_ptr < s->size)
+        av_log(s->avctx, AV_LOG_ERROR, " MS RLE: ended frame decode with bytes left over (%d < %d)\n",
+            stream_ptr, s->size);
+}
+
+
+
 static void msrle_decode_pal8(MsrleContext *s)
 {
     int stream_ptr = 0;
@@ -188,7 +283,17 @@
 	memcpy(s->frame.data[0], s->prev_frame.data[0], 
         s->frame.linesize[0] * s->avctx->height);
 
-    msrle_decode_pal8(s);
+    switch (avctx->bits_per_sample) {
+        case 8:
+            msrle_decode_pal8(s);
+            break;
+        case 4:
+            msrle_decode_pal4(s);
+            break;
+        default:
+            av_log(avctx, AV_LOG_ERROR, "Don't know how to decode depth %u.\n",
+                   avctx->bits_per_sample);
+    }
 
     if (s->prev_frame.data[0])
         avctx->release_buffer(avctx, &s->prev_frame);