mirror of
https://github.com/mpv-player/mpv
synced 2025-03-20 10:17:31 +00:00
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
This commit is contained in:
parent
28695eedd8
commit
72c07064bd
@ -65,8 +65,8 @@
|
||||
{"stereo", &fakemono, CONF_TYPE_INT, CONF_RANGE, 0, 2},
|
||||
#endif
|
||||
|
||||
{"afm", &audio_family, CONF_TYPE_INT, CONF_RANGE, 0, 13}, // keep ranges in sync
|
||||
{"vfm", &video_family, CONF_TYPE_INT, CONF_RANGE, 0, 10}, // with codec-cfg.c
|
||||
{"afm", &audio_family, CONF_TYPE_INT, CONF_MIN, 0, 13}, // keep ranges in sync
|
||||
{"vfm", &video_family, CONF_TYPE_INT, CONF_MIN, 0, 10}, // with codec-cfg.c
|
||||
{"ac", &audio_codec, CONF_TYPE_STRING, 0, 0, 0},
|
||||
{"vc", &video_codec, CONF_TYPE_STRING, 0, 0, 0},
|
||||
|
||||
|
@ -223,6 +223,7 @@ static short get_driver(char *s,int audioflag)
|
||||
"raw",
|
||||
"rle",
|
||||
"xanim",
|
||||
"msvidc",
|
||||
NULL
|
||||
};
|
||||
char **drv=audioflag?audiodrv:videodrv;
|
||||
|
@ -42,6 +42,7 @@
|
||||
#define VFM_RAW 8
|
||||
#define VFM_RLE 9
|
||||
#define VFM_XANIM 10
|
||||
#define VFM_MSVIDC 11
|
||||
|
||||
#ifndef GUID_TYPE
|
||||
#define GUID_TYPE
|
||||
|
37
dec_video.c
37
dec_video.c
@ -86,6 +86,23 @@ int divx_quality=0;
|
||||
void AVI_Decode_RLE8(char *image,char *delta,int tdsize,
|
||||
unsigned int *map,int imagex,int imagey,unsigned char x11_bytes_pixel);
|
||||
|
||||
void AVI_Decode_Video1_16(
|
||||
char *encoded,
|
||||
int encoded_size,
|
||||
char *decoded,
|
||||
int width,
|
||||
int height,
|
||||
int bytes_per_pixel);
|
||||
|
||||
void AVI_Decode_Video1_8(
|
||||
char *encoded,
|
||||
int encoded_size,
|
||||
char *decoded,
|
||||
int width,
|
||||
int height,
|
||||
unsigned char *palette_map,
|
||||
int bytes_per_pixel);
|
||||
|
||||
//**************************************************************************//
|
||||
// The OpenDivX stuff:
|
||||
//**************************************************************************//
|
||||
@ -450,6 +467,12 @@ switch(sh_video->codec->driver){
|
||||
}
|
||||
}
|
||||
break;
|
||||
case VFM_MSVIDC: {
|
||||
int bpp=((out_fmt&255)+7)/8; // RGB only
|
||||
sh_video->our_out_buffer =
|
||||
(char*)memalign(64, sh_video->disp_w*sh_video->disp_h*bpp); // FIXME!!!
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
sh_video->inited=1;
|
||||
@ -681,6 +704,19 @@ if(verbose>1){
|
||||
sh_video->disp_w,sh_video->disp_h,((out_fmt&255)+7)/8);
|
||||
blit_frame=3;
|
||||
break;
|
||||
case VFM_MSVIDC:
|
||||
if (sh_video->bih->biBitCount == 16)
|
||||
AVI_Decode_Video1_16(
|
||||
start, in_size, sh_video->our_out_buffer,
|
||||
sh_video->disp_w, sh_video->disp_h,
|
||||
((out_fmt&255)+7)/8);
|
||||
else
|
||||
AVI_Decode_Video1_8(
|
||||
start, in_size, sh_video->our_out_buffer,
|
||||
sh_video->disp_w, sh_video->disp_h,
|
||||
(char *)sh_video->bih+40, ((out_fmt&255)+7)/8);
|
||||
blit_frame = 3;
|
||||
break;
|
||||
} // switch
|
||||
//------------------------ frame decoded. --------------------
|
||||
|
||||
@ -727,3 +763,4 @@ case 2:
|
||||
return blit_frame;
|
||||
}
|
||||
|
||||
|
||||
|
351
msvidc.c
Normal file
351
msvidc.c
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user