diff libmpcodecs/native/msvidc.c @ 5602:628c85c15c7b

moved to libmpcodecs/native/
author arpi
date Sat, 13 Apr 2002 18:03:02 +0000
parents msvidc.c@31cd2e0bb961
children 0380dfad2db9
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmpcodecs/native/msvidc.c	Sat Apr 13 18:03:02 2002 +0000
@@ -0,0 +1,393 @@
+/*
+    Microsoft Video 1 Decoder
+    
+    (C) 2001 Mike Melanson
+    
+    The description of the algorithm you can read here:
+      http://www.pcisys.net/~melanson/codecs/
+
+    32bpp support (c) alex
+*/
+
+#include "config.h"
+#include "bswap.h"
+
+#define LE_16(x) (le2me_16(*(unsigned short *)(x)))
+
+#define DECODE_BGR555_TO_BGR888(x) \
+        x.c1_b = (x.c1 >> 7) & 0xF8; \
+        x.c1_g = (x.c1 >> 2) & 0xF8; \
+        x.c1_r = (x.c1 << 3) & 0xF8; \
+        x.c2_b = (x.c2 >> 7) & 0xF8; \
+        x.c2_g = (x.c2 >> 2) & 0xF8; \
+        x.c2_r = (x.c2 << 3) & 0xF8;
+
+#define DECODE_PALETTE_TO_BGR888(x) \
+        x.c1_b = palette_map[x.c1 * 4 + 2]; \
+        x.c1_g = palette_map[x.c1 * 4 + 1]; \
+        x.c1_r = palette_map[x.c1 * 4 + 0]; \
+        x.c2_b = palette_map[x.c2 * 4 + 2]; \
+        x.c2_g = palette_map[x.c2 * 4 + 1]; \
+        x.c2_r = palette_map[x.c2 * 4 + 0];
+
+struct
+{
+  unsigned short c1, c2;
+  unsigned char c1_r, c1_g, c1_b;
+  unsigned char c2_r, c2_g, c2_b;
+} quad[2][2];
+
+void AVI_Decode_Video1_16(
+  char *encoded,
+  int encoded_size,
+  char *decoded,
+  int width,
+  int height,
+  int bytes_per_pixel)
+{
+  int block_ptr, pixel_ptr;
+  int total_blocks;
+  int pixel_x, pixel_y;  // pixel width and height iterators
+  int block_x, block_y;  // block width and height iterators
+  int blocks_wide, blocks_high;  // width and height in 4x4 blocks
+  int block_inc;
+  int row_dec;
+
+  // decoding parameters
+  int stream_ptr;
+  unsigned char byte_a, byte_b;
+  unsigned short flags;
+  int skip_blocks;
+
+  stream_ptr = 0;
+  skip_blocks = 0;
+  blocks_wide = width / 4;
+  blocks_high = height / 4;
+  total_blocks = blocks_wide * blocks_high;
+  block_inc = 4 * bytes_per_pixel;
+  row_dec = (width + 4) * bytes_per_pixel;
+
+  for (block_y = blocks_high; block_y > 0; block_y--)
+  {
+    block_ptr = ((block_y * 4) - 1) * (width * bytes_per_pixel);
+    for (block_x = blocks_wide; block_x > 0; block_x--)
+    {
+      // check if this block should be skipped
+      if (skip_blocks)
+      {
+        block_ptr += block_inc;
+        skip_blocks--;
+        total_blocks--;
+        continue;
+      }
+
+      pixel_ptr = block_ptr;
+
+      // get the next two bytes in the encoded data stream
+      byte_a = encoded[stream_ptr++];
+      byte_b = encoded[stream_ptr++];
+
+      // check if the decode is finished
+      if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0))
+        return;
+
+      // check if this is a skip code
+      else if ((byte_b & 0xFC) == 0x84)
+      {
+        // but don't count the current block
+        skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1;
+      }
+
+      // check if this is in the 2- or 8-color classes
+      else if (byte_b < 0x80)
+      {
+        flags = (byte_b << 8) | byte_a;
+
+        quad[0][0].c1 = LE_16(&encoded[stream_ptr]);
+        stream_ptr += 2;
+        quad[0][0].c2 = LE_16(&encoded[stream_ptr]);
+        stream_ptr += 2;
+
+        DECODE_BGR555_TO_BGR888(quad[0][0]);
+
+        if (quad[0][0].c1 & 0x8000)
+        {
+          // 8-color encoding
+          quad[1][0].c1 = LE_16(&encoded[stream_ptr]);
+          stream_ptr += 2;
+          quad[1][0].c2 = LE_16(&encoded[stream_ptr]);
+          stream_ptr += 2;
+          quad[0][1].c1 = LE_16(&encoded[stream_ptr]);
+          stream_ptr += 2;
+          quad[0][1].c2 = LE_16(&encoded[stream_ptr]);
+          stream_ptr += 2;
+          quad[1][1].c1 = LE_16(&encoded[stream_ptr]);
+          stream_ptr += 2;
+          quad[1][1].c2 = LE_16(&encoded[stream_ptr]);
+          stream_ptr += 2;
+
+          DECODE_BGR555_TO_BGR888(quad[0][1]);
+          DECODE_BGR555_TO_BGR888(quad[1][0]);
+          DECODE_BGR555_TO_BGR888(quad[1][1]);
+
+          for (pixel_y = 0; pixel_y < 4; pixel_y++)
+          {
+            for (pixel_x = 0; pixel_x < 4; pixel_x++)
+            {
+              if (flags & 1)
+              {
+                decoded[pixel_ptr++] = quad[pixel_x >> 1][pixel_y >> 1].c1_r;
+                decoded[pixel_ptr++] = quad[pixel_x >> 1][pixel_y >> 1].c1_g;
+                decoded[pixel_ptr++] = quad[pixel_x >> 1][pixel_y >> 1].c1_b;
+		if (bytes_per_pixel == 4) /* 32bpp */
+		    pixel_ptr++;
+              }
+              else
+              {
+                decoded[pixel_ptr++] = quad[pixel_x >> 1][pixel_y >> 1].c2_r;
+                decoded[pixel_ptr++] = quad[pixel_x >> 1][pixel_y >> 1].c2_g;
+                decoded[pixel_ptr++] = quad[pixel_x >> 1][pixel_y >> 1].c2_b;
+		if (bytes_per_pixel == 4) /* 32bpp */
+		    pixel_ptr++;
+              }
+
+              // get the next flag ready to go
+              flags >>= 1;
+            }
+            pixel_ptr -= row_dec;
+          }
+        }
+        else
+        {
+          // 2-color encoding
+          for (pixel_y = 0; pixel_y < 4; pixel_y++)
+          {
+            for (pixel_x = 0; pixel_x < 4; pixel_x++)
+            {
+              if (flags & 1)
+              {
+                decoded[pixel_ptr++] = quad[0][0].c1_r;
+                decoded[pixel_ptr++] = quad[0][0].c1_g;
+                decoded[pixel_ptr++] = quad[0][0].c1_b;
+		if (bytes_per_pixel == 4) /* 32bpp */
+		    pixel_ptr++;
+              }
+              else
+              {
+                decoded[pixel_ptr++] = quad[0][0].c2_r;
+                decoded[pixel_ptr++] = quad[0][0].c2_g;
+                decoded[pixel_ptr++] = quad[0][0].c2_b;
+		if (bytes_per_pixel == 4) /* 32bpp */
+		    pixel_ptr++;
+              }
+
+              // get the next flag ready to go
+              flags >>= 1;
+            }
+            pixel_ptr -= row_dec;
+          }
+        }
+      }
+
+      // otherwise, it's a 1-color block
+      else
+      {
+        quad[0][0].c1 = (byte_b << 8) | byte_a;
+        DECODE_BGR555_TO_BGR888(quad[0][0]);
+
+        for (pixel_y = 0; pixel_y < 4; pixel_y++)
+        {
+          for (pixel_x = 0; pixel_x < 4; pixel_x++)
+          {
+            decoded[pixel_ptr++] = quad[0][0].c1_r;
+            decoded[pixel_ptr++] = quad[0][0].c1_g;
+            decoded[pixel_ptr++] = quad[0][0].c1_b;
+	    if (bytes_per_pixel == 4) /* 32bpp */
+		pixel_ptr++;
+          }
+          pixel_ptr -= row_dec;
+        }
+      }
+
+      block_ptr += block_inc;
+      total_blocks--;
+    }
+  }
+}
+
+void AVI_Decode_Video1_8(
+  char *encoded,
+  int encoded_size,
+  char *decoded,
+  int width,
+  int height,
+  unsigned char *palette_map,
+  int bytes_per_pixel)
+{
+  int block_ptr, pixel_ptr;
+  int total_blocks;
+  int pixel_x, pixel_y;  // pixel width and height iterators
+  int block_x, block_y;  // block width and height iterators
+  int blocks_wide, blocks_high;  // width and height in 4x4 blocks
+  int block_inc;
+  int row_dec;
+
+  // decoding parameters
+  int stream_ptr;
+  unsigned char byte_a, byte_b;
+  unsigned short flags;
+  int skip_blocks;
+
+  stream_ptr = 0;
+  skip_blocks = 0;
+  blocks_wide = width / 4;
+  blocks_high = height / 4;
+  total_blocks = blocks_wide * blocks_high;
+  block_inc = 4 * bytes_per_pixel;
+  row_dec = (width + 4) * bytes_per_pixel;
+
+  for (block_y = blocks_high; block_y > 0; block_y--)
+  {
+    block_ptr = ((block_y * 4) - 1) * (width * bytes_per_pixel);
+    for (block_x = blocks_wide; block_x > 0; block_x--)
+    {
+      // check if this block should be skipped
+      if (skip_blocks)
+      {
+        block_ptr += block_inc;
+        skip_blocks--;
+        total_blocks--;
+        continue;
+      }
+
+      pixel_ptr = block_ptr;
+
+      // get the next two bytes in the encoded data stream
+      byte_a = encoded[stream_ptr++];
+      byte_b = encoded[stream_ptr++];
+
+      // check if the decode is finished
+      if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0))
+        return;
+
+      // check if this is a skip code
+      else if ((byte_b & 0xFC) == 0x84)
+      {
+        // but don't count the current block
+        skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1;
+      }
+
+      // check if this is a 2-color block
+      else if (byte_b < 0x80)
+      {
+        flags = (byte_b << 8) | byte_a;
+
+        quad[0][0].c1 = (unsigned char)encoded[stream_ptr++];
+        quad[0][0].c2 = (unsigned char)encoded[stream_ptr++];
+
+        DECODE_PALETTE_TO_BGR888(quad[0][0]);
+
+        // 2-color encoding
+        for (pixel_y = 0; pixel_y < 4; pixel_y++)
+        {
+          for (pixel_x = 0; pixel_x < 4; pixel_x++)
+          {
+            if (flags & 1)
+            {
+              decoded[pixel_ptr++] = quad[0][0].c1_r;
+              decoded[pixel_ptr++] = quad[0][0].c1_g;
+              decoded[pixel_ptr++] = quad[0][0].c1_b;
+	      if (bytes_per_pixel == 4) /* 32bpp */
+		pixel_ptr++;
+            }
+            else
+            {
+              decoded[pixel_ptr++] = quad[0][0].c2_r;
+              decoded[pixel_ptr++] = quad[0][0].c2_g;
+              decoded[pixel_ptr++] = quad[0][0].c2_b;
+	      if (bytes_per_pixel == 4) /* 32bpp */
+		pixel_ptr++;
+            }
+
+            // get the next flag ready to go
+            flags >>= 1;
+          }
+          pixel_ptr -= row_dec;
+        }
+      }
+
+      // check if it's an 8-color block
+      else if (byte_b >= 0x90)
+      {
+        flags = (byte_b << 8) | byte_a;
+
+        quad[0][0].c1 = (unsigned char)encoded[stream_ptr++];
+        quad[0][0].c2 = (unsigned char)encoded[stream_ptr++];
+        quad[1][0].c1 = (unsigned char)encoded[stream_ptr++];
+        quad[1][0].c2 = (unsigned char)encoded[stream_ptr++];
+
+        quad[0][1].c1 = (unsigned char)encoded[stream_ptr++];
+        quad[0][1].c2 = (unsigned char)encoded[stream_ptr++];
+        quad[1][1].c1 = (unsigned char)encoded[stream_ptr++];
+        quad[1][1].c2 = (unsigned char)encoded[stream_ptr++];
+
+        DECODE_PALETTE_TO_BGR888(quad[0][0]);
+        DECODE_PALETTE_TO_BGR888(quad[0][1]);
+        DECODE_PALETTE_TO_BGR888(quad[1][0]);
+        DECODE_PALETTE_TO_BGR888(quad[1][1]);
+
+        for (pixel_y = 0; pixel_y < 4; pixel_y++)
+        {
+          for (pixel_x = 0; pixel_x < 4; pixel_x++)
+          {
+            if (flags & 1)
+            {
+              decoded[pixel_ptr++] = quad[pixel_x >> 1][pixel_y >> 1].c1_r;
+              decoded[pixel_ptr++] = quad[pixel_x >> 1][pixel_y >> 1].c1_g;
+              decoded[pixel_ptr++] = quad[pixel_x >> 1][pixel_y >> 1].c1_b;
+	      if (bytes_per_pixel == 4) /* 32bpp */
+		pixel_ptr++;
+            }
+            else
+            {
+              decoded[pixel_ptr++] = quad[pixel_x >> 1][pixel_y >> 1].c2_r;
+              decoded[pixel_ptr++] = quad[pixel_x >> 1][pixel_y >> 1].c2_g;
+              decoded[pixel_ptr++] = quad[pixel_x >> 1][pixel_y >> 1].c2_b;
+	      if (bytes_per_pixel == 4) /* 32bpp */
+		pixel_ptr++;
+            }
+
+            // get the next flag ready to go
+            flags >>= 1;
+          }
+          pixel_ptr -= row_dec;
+        }
+      }
+
+      // otherwise, it's a 1-color block
+      else
+      {
+        // init c2 along with c1 just so c2 is a known value for macro
+        quad[0][0].c1 = quad[0][0].c2 = byte_a;
+        DECODE_PALETTE_TO_BGR888(quad[0][0]);
+
+        for (pixel_y = 0; pixel_y < 4; pixel_y++)
+        {
+          for (pixel_x = 0; pixel_x < 4; pixel_x++)
+          {
+            decoded[pixel_ptr++] = quad[0][0].c1_r;
+            decoded[pixel_ptr++] = quad[0][0].c1_g;
+            decoded[pixel_ptr++] = quad[0][0].c1_b;
+	    if (bytes_per_pixel == 4) /* 32bpp */
+		pixel_ptr++;
+          }
+          pixel_ptr -= row_dec;
+        }
+      }
+
+      block_ptr += block_inc;
+      total_blocks--;
+    }
+  }
+}
+