mirror of https://github.com/mpv-player/mpv
initial commit
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@3156 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
b5c58f8381
commit
56aa85c7a2
|
@ -0,0 +1,273 @@
|
|||
/*
|
||||
FLI Decoder for MPlayer
|
||||
|
||||
(C) 2001 Mike Melanson
|
||||
*/
|
||||
|
||||
#define LE_16(x) *(unsigned short *)(x)
|
||||
#define LE_32(x) *(unsigned int *)(x)
|
||||
|
||||
#define FLI_256_COLOR 4
|
||||
#define FLI_DELTA 7
|
||||
#define FLI_COLOR 11
|
||||
#define FLI_LC 12
|
||||
#define FLI_BLACK 13
|
||||
#define FLI_BRUN 15
|
||||
#define FLI_COPY 16
|
||||
#define FLI_MINI 18
|
||||
|
||||
// 256 RGB entries; 25% of these bytes will be unused, but it's faster
|
||||
// to index 4-byte entries
|
||||
static unsigned char palette[256 * 4];
|
||||
|
||||
void AVI_Decode_Fli(
|
||||
unsigned char *encoded,
|
||||
int encoded_size,
|
||||
unsigned char *decoded,
|
||||
int width,
|
||||
int height,
|
||||
int bytes_per_pixel)
|
||||
{
|
||||
int stream_ptr = 0;
|
||||
int pixel_ptr;
|
||||
int palette_ptr1;
|
||||
int palette_ptr2;
|
||||
|
||||
unsigned int frame_size;
|
||||
int num_chunks;
|
||||
|
||||
unsigned int chunk_size;
|
||||
int chunk_type;
|
||||
|
||||
int i, j;
|
||||
|
||||
int color_packets;
|
||||
int color_changes;
|
||||
int color_scale;
|
||||
|
||||
int lines;
|
||||
int compressed_lines;
|
||||
int starting_line;
|
||||
signed short line_packets;
|
||||
int y_ptr;
|
||||
int line_inc;
|
||||
signed char byte_run;
|
||||
|
||||
frame_size = LE_32(&encoded[stream_ptr]);
|
||||
stream_ptr += 6; // skip the magic number
|
||||
num_chunks = LE_16(&encoded[stream_ptr]);
|
||||
stream_ptr += 10; // skip padding
|
||||
|
||||
// iterate through the chunks
|
||||
frame_size -= 16;
|
||||
while ((frame_size > 0) && (num_chunks > 0))
|
||||
{
|
||||
chunk_size = LE_32(&encoded[stream_ptr]);
|
||||
stream_ptr += 4;
|
||||
chunk_type = LE_16(&encoded[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
|
||||
switch (chunk_type)
|
||||
{
|
||||
case FLI_256_COLOR:
|
||||
case FLI_COLOR:
|
||||
if (chunk_type == FLI_COLOR)
|
||||
color_scale = 4;
|
||||
else
|
||||
color_scale = 1;
|
||||
// set up the palette
|
||||
color_packets = LE_16(&encoded[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
palette_ptr1 = 0;
|
||||
for (i = 0; i < color_packets; i++)
|
||||
{
|
||||
// first byte is how many colors to skip
|
||||
palette_ptr1 += (encoded[stream_ptr++] * 4);
|
||||
// next byte indicates how many entries to change
|
||||
color_changes = encoded[stream_ptr++];
|
||||
// if there are 0 color changes, there are actually 256
|
||||
if (color_changes == 0)
|
||||
color_changes = 256;
|
||||
for (j = 0; j < color_changes; j++)
|
||||
{
|
||||
palette[palette_ptr1++] = encoded[stream_ptr + 2] * color_scale;
|
||||
palette[palette_ptr1++] = encoded[stream_ptr + 1] * color_scale;
|
||||
palette[palette_ptr1++] = encoded[stream_ptr + 0] * color_scale;
|
||||
palette_ptr1++;
|
||||
stream_ptr += 3;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FLI_DELTA:
|
||||
line_inc = width * bytes_per_pixel;
|
||||
y_ptr = 0;
|
||||
compressed_lines = LE_16(&encoded[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
while (compressed_lines > 0)
|
||||
{
|
||||
line_packets = LE_16(&encoded[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
if (line_packets < 0)
|
||||
{
|
||||
line_packets = -line_packets;
|
||||
y_ptr += (line_packets * line_inc);
|
||||
}
|
||||
else
|
||||
{
|
||||
pixel_ptr = y_ptr;
|
||||
for (i = 0; i < line_packets; i++)
|
||||
{
|
||||
// account for the skip bytes
|
||||
pixel_ptr += encoded[stream_ptr++] * 3;
|
||||
byte_run = encoded[stream_ptr++];
|
||||
if (byte_run < 0)
|
||||
{
|
||||
byte_run = -byte_run;
|
||||
palette_ptr1 = encoded[stream_ptr++] * 4;
|
||||
palette_ptr2 = encoded[stream_ptr++] * 4;
|
||||
for (j = 0; j < byte_run; j++)
|
||||
{
|
||||
decoded[pixel_ptr++] = palette[palette_ptr1 + 0];
|
||||
decoded[pixel_ptr++] = palette[palette_ptr1 + 1];
|
||||
decoded[pixel_ptr++] = palette[palette_ptr1 + 2];
|
||||
|
||||
decoded[pixel_ptr++] = palette[palette_ptr2 + 0];
|
||||
decoded[pixel_ptr++] = palette[palette_ptr2 + 1];
|
||||
decoded[pixel_ptr++] = palette[palette_ptr2 + 2];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = 0; j < byte_run * 2; j++)
|
||||
{
|
||||
palette_ptr1 = encoded[stream_ptr++] * 4;
|
||||
decoded[pixel_ptr++] = palette[palette_ptr1 + 0];
|
||||
decoded[pixel_ptr++] = palette[palette_ptr1 + 1];
|
||||
decoded[pixel_ptr++] = palette[palette_ptr1 + 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
y_ptr += line_inc;
|
||||
compressed_lines--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FLI_LC:
|
||||
// line compressed
|
||||
line_inc = width * bytes_per_pixel;
|
||||
starting_line = LE_16(&encoded[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
y_ptr = starting_line * line_inc;
|
||||
|
||||
compressed_lines = LE_16(&encoded[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
while (compressed_lines > 0)
|
||||
{
|
||||
pixel_ptr = y_ptr;
|
||||
line_packets = encoded[stream_ptr++];
|
||||
if (line_packets > 0)
|
||||
{
|
||||
for (i = 0; i < line_packets; i++)
|
||||
{
|
||||
// account for the skip bytes
|
||||
pixel_ptr += encoded[stream_ptr++] * 3;
|
||||
byte_run = encoded[stream_ptr++];
|
||||
if (byte_run > 0)
|
||||
{
|
||||
for (j = 0; j < byte_run; j++)
|
||||
{
|
||||
palette_ptr1 = encoded[stream_ptr++] * 4;
|
||||
decoded[pixel_ptr++] = palette[palette_ptr1 + 0];
|
||||
decoded[pixel_ptr++] = palette[palette_ptr1 + 1];
|
||||
decoded[pixel_ptr++] = palette[palette_ptr1 + 2];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
byte_run = -byte_run;
|
||||
palette_ptr1 = encoded[stream_ptr++] * 4;
|
||||
for (j = 0; j < byte_run; j++)
|
||||
{
|
||||
decoded[pixel_ptr++] = palette[palette_ptr1 + 0];
|
||||
decoded[pixel_ptr++] = palette[palette_ptr1 + 1];
|
||||
decoded[pixel_ptr++] = palette[palette_ptr1 + 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
y_ptr += line_inc;
|
||||
compressed_lines--;
|
||||
}
|
||||
break;
|
||||
|
||||
case FLI_BLACK:
|
||||
// set the whole frame to color 0 (which is usually black)
|
||||
for (pixel_ptr = 0; pixel_ptr < (width * height * 3); pixel_ptr++)
|
||||
{
|
||||
decoded[pixel_ptr++] = palette[0];
|
||||
decoded[pixel_ptr++] = palette[1];
|
||||
decoded[pixel_ptr++] = palette[2];
|
||||
}
|
||||
break;
|
||||
|
||||
case FLI_BRUN:
|
||||
// byte run compression
|
||||
line_inc = width * bytes_per_pixel;
|
||||
y_ptr = 0;
|
||||
for (lines = 0; lines < height; lines++)
|
||||
{
|
||||
pixel_ptr = y_ptr;
|
||||
line_packets = encoded[stream_ptr++];
|
||||
for (i = 0; i < line_packets; i++)
|
||||
{
|
||||
byte_run = encoded[stream_ptr++];
|
||||
if (byte_run > 0)
|
||||
{
|
||||
palette_ptr1 = encoded[stream_ptr++] * 4;
|
||||
for (j = 0; j < byte_run; j++)
|
||||
{
|
||||
decoded[pixel_ptr++] = palette[palette_ptr1 + 0];
|
||||
decoded[pixel_ptr++] = palette[palette_ptr1 + 1];
|
||||
decoded[pixel_ptr++] = palette[palette_ptr1 + 2];
|
||||
}
|
||||
}
|
||||
else // copy bytes if byte_run < 0
|
||||
{
|
||||
byte_run = -byte_run;
|
||||
for (j = 0; j < byte_run; j++)
|
||||
{
|
||||
palette_ptr1 = encoded[stream_ptr++] * 4;
|
||||
decoded[pixel_ptr++] = palette[palette_ptr1 + 0];
|
||||
decoded[pixel_ptr++] = palette[palette_ptr1 + 1];
|
||||
decoded[pixel_ptr++] = palette[palette_ptr1 + 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
y_ptr += line_inc;
|
||||
}
|
||||
break;
|
||||
|
||||
case FLI_COPY:
|
||||
// currently unimplemented
|
||||
printf ("FLI_COPY chunk (currently unimplemented)\n");
|
||||
stream_ptr += chunk_size - 6;
|
||||
break;
|
||||
|
||||
case FLI_MINI:
|
||||
// sort of a thumbnail? disregard this chunk...
|
||||
stream_ptr += chunk_size - 6;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("FLI: Unrecognized chunk type: %d\n", chunk_type);
|
||||
break;
|
||||
}
|
||||
|
||||
frame_size -= chunk_size;
|
||||
num_chunks--;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue