summaryrefslogtreecommitdiffstats
path: root/msvidc.c
diff options
context:
space:
mode:
authorarpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2>2001-11-11 13:35:00 +0000
committerarpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2>2001-11-11 13:35:00 +0000
commit72c07064bd85402dcf2ef2f0e2e40e5e5da4d3fa (patch)
tree80c9159ef0d5276c5da70bacbb6cdfc13ba87bb1 /msvidc.c
parent28695eedd88737c462e3f9980be4a40377e2d2b3 (diff)
downloadmpv-72c07064bd85402dcf2ef2f0e2e40e5e5da4d3fa.tar.bz2
mpv-72c07064bd85402dcf2ef2f0e2e40e5e5da4d3fa.tar.xz
ms video1 (cram) codecs by Mike Melanson <melanson@pcisys.net>
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@2828 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'msvidc.c')
-rw-r--r--msvidc.c351
1 files changed, 351 insertions, 0 deletions
diff --git a/msvidc.c b/msvidc.c
new file mode 100644
index 0000000000..d02e9d5932
--- /dev/null
+++ b/msvidc.c
@@ -0,0 +1,351 @@
+
+#define LE_16(x) *(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 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;
+ 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--;
+ 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))
+ 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;
+ }
+ 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;
+ }
+
+ // 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;
+ }
+ 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;
+ }
+
+ // 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;
+ }
+ pixel_ptr -= row_dec;
+ }
+ }
+
+ block_ptr += block_inc;
+ }
+ }
+}
+
+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 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;
+ 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--;
+ 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))
+ 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;
+ }
+ 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;
+ }
+
+ // 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)
+ {
+ // 8-color encoding
+ 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;
+ }
+ 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;
+ }
+
+ // 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;
+ }
+ pixel_ptr -= row_dec;
+ }
+ }
+
+ block_ptr += block_inc;
+ }
+ }
+}
+