8 and 16bpp qtrle support

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@6721 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
alex 2002-07-12 17:49:04 +00:00
parent 4d25d1b683
commit 3d0493357f
2 changed files with 242 additions and 12 deletions

View File

@ -2,6 +2,7 @@
Quicktime Animation (RLE) Decoder for MPlayer
(C) 2001 Mike Melanson
8 and 16bpp support by Alex Beregszaszi
*/
#include "config.h"
@ -10,9 +11,164 @@
#define BE_16(x) (be2me_16(*(unsigned short *)(x)))
#define BE_32(x) (be2me_32(*(unsigned int *)(x)))
// 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 qt_decode_rle8(
unsigned char *encoded,
int encoded_size,
unsigned char *decoded,
int width,
int height,
int bytes_per_pixel)
{
int stream_ptr;
int header;
int start_line;
int lines_to_change;
signed char rle_code;
int row_ptr, pixel_ptr;
int row_inc = bytes_per_pixel * width;
unsigned char pixel;
// check if this frame is even supposed to change
if (encoded_size < 8)
return;
// start after the chunk size
stream_ptr = 4;
// fetch the header
header = BE_16(&encoded[stream_ptr]);
stream_ptr += 2;
// if a header is present, fetch additional decoding parameters
if (header & 0x0008)
{
start_line = BE_16(&encoded[stream_ptr]);
stream_ptr += 4;
lines_to_change = BE_16(&encoded[stream_ptr]);
stream_ptr += 4;
}
else
{
start_line = 0;
lines_to_change = height;
}
row_ptr = row_inc * start_line;
while (lines_to_change--)
{
pixel_ptr = row_ptr + ((encoded[stream_ptr++] - 1) * bytes_per_pixel);
while (stream_ptr < encoded_size &&
(rle_code = (signed char)encoded[stream_ptr++]) != -1)
{
if (rle_code == 0)
// there's another skip code in the stream
pixel_ptr += ((encoded[stream_ptr++] - 1) * bytes_per_pixel);
else if (rle_code < 0)
{
// decode the run length code
rle_code = -rle_code;
pixel = encoded[stream_ptr++];
while (rle_code--)
{
decoded[pixel_ptr++] = pixel;
}
}
else
{
// copy pixels directly to output
while (rle_code--)
{
decoded[pixel_ptr++] = encoded[stream_ptr + 0];
stream_ptr += 1;
}
}
}
row_ptr += row_inc;
}
}
void qt_decode_rle16(
unsigned char *encoded,
int encoded_size,
unsigned char *decoded,
int width,
int height,
int bytes_per_pixel)
{
int stream_ptr;
int header;
int start_line;
int lines_to_change;
signed char rle_code;
int row_ptr, pixel_ptr;
int row_inc = bytes_per_pixel * width;
unsigned char p1, p2;
// check if this frame is even supposed to change
if (encoded_size < 8)
return;
// start after the chunk size
stream_ptr = 4;
// fetch the header
header = BE_16(&encoded[stream_ptr]);
stream_ptr += 2;
// if a header is present, fetch additional decoding parameters
if (header & 0x0008)
{
start_line = BE_16(&encoded[stream_ptr]);
stream_ptr += 4;
lines_to_change = BE_16(&encoded[stream_ptr]);
stream_ptr += 4;
}
else
{
start_line = 0;
lines_to_change = height;
}
row_ptr = row_inc * start_line;
while (lines_to_change--)
{
pixel_ptr = row_ptr + ((encoded[stream_ptr++] - 1) * bytes_per_pixel);
while (stream_ptr < encoded_size &&
(rle_code = (signed char)encoded[stream_ptr++]) != -1)
{
if (rle_code == 0)
// there's another skip code in the stream
pixel_ptr += ((encoded[stream_ptr++] - 1) * bytes_per_pixel);
else if (rle_code < 0)
{
// decode the run length code
rle_code = -rle_code;
p1 = encoded[stream_ptr++];
p2 = encoded[stream_ptr++];
while (rle_code--)
{
decoded[pixel_ptr++] = p2;
decoded[pixel_ptr++] = p1;
}
}
else
{
// copy pixels directly to output
while (rle_code--)
{
decoded[pixel_ptr++] = encoded[stream_ptr + 1];
decoded[pixel_ptr++] = encoded[stream_ptr + 0];
stream_ptr += 2;
}
}
}
row_ptr += row_inc;
}
}
void qt_decode_rle24(
unsigned char *encoded,
@ -113,6 +269,24 @@ void qt_decode_rle(
{
switch (encoded_bpp)
{
case 8:
qt_decode_rle8(
encoded,
encoded_size,
decoded,
width,
height,
bytes_per_pixel);
break;
case 16:
qt_decode_rle16(
encoded,
encoded_size,
decoded,
width,
height,
bytes_per_pixel);
break;
case 24:
qt_decode_rle24(
encoded,

View File

@ -17,27 +17,79 @@ static vd_info_t info = {
LIBVD_EXTERN(qtrle)
typedef struct {
int depth;
void *palette;
} vd_qtrle_ctx;
// to set/get/query special features/parameters
static int control(sh_video_t *sh,int cmd,void* arg,...){
vd_qtrle_ctx *ctx = sh->context;
switch(cmd)
{
case VDCTRL_QUERY_FORMAT:
{
int req_format = *((int*)arg);
/* qtrle24 supports 32bit output too */
if ((req_format == (IMGFMT_BGR|ctx->depth)) ||
((IMGFMT_BGR_DEPTH(req_format) == 32) && (ctx->depth == 24)))
return(CONTROL_TRUE);
else
return(CONTROL_FALSE);
}
}
return CONTROL_UNKNOWN;
}
// init driver
static int init(sh_video_t *sh){
if (sh->bih->biBitCount != 24){
mp_msg(MSGT_DECVIDEO,MSGL_ERR,
" *** FYI: This Quicktime file is using %d-bit RLE Animation\n" \
" encoding, which is not yet supported by MPlayer. But if you upload\n" \
" this Quicktime file to the MPlayer FTP, the team could look at it.\n",
sh->bih->biBitCount);
return 0;
}
vd_qtrle_ctx *ctx;
return mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_BGR24);
ctx = sh->context = malloc(sizeof(vd_qtrle_ctx));
if (!ctx)
return(0);
memset(ctx, 0, sizeof(vd_qtrle_ctx));
if (!sh->bih)
return(0);
ctx->depth = sh->bih->biBitCount;
switch(ctx->depth)
{
case 2:
case 4:
case 8:
if (sh->bih->biSize > 40)
{
ctx->palette = malloc(sh->bih->biSize-40);
memcpy(ctx->palette, sh->bih+40, sh->bih->biSize-40);
}
break;
case 16:
ctx->depth--; /* this is the trick ;) */
break;
case 24:
break;
default:
mp_msg(MSGT_DECVIDEO,MSGL_ERR,
"*** FYI: This Quicktime file is using %d-bit RLE Animation\n" \
"encoding, which is not yet supported by MPlayer. But if you upload\n" \
"this Quicktime file to the MPlayer FTP, the team could look at it.\n",
ctx->depth);
return(0);
}
return mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_BGR|ctx->depth);
}
// uninit driver
static void uninit(sh_video_t *sh){
vd_qtrle_ctx *ctx = sh->context;
if (ctx->palette)
free(ctx->palette);
free(ctx);
}
//mp_image_t* mpcodecs_get_image(sh_video_t *sh, int mp_imgtype, int mp_imgflag, int w, int h);
@ -53,6 +105,7 @@ void qt_decode_rle(
// decode a frame
static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){
vd_qtrle_ctx *ctx = sh->context;
mp_image_t* mpi;
if(len<=0) return NULL; // skipped frame
@ -65,6 +118,9 @@ static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){
sh->disp_w, sh->disp_h,
sh->bih->biBitCount,
mpi->bpp/8);
if (ctx->palette)
mpi->planes[1] = ctx->palette;
return mpi;
}