Mercurial > mplayer.hg
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--; + } + } +} +